From db726862ae2224167918a65a880c41cc6ca8f478 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Mon, 28 Jun 2021 20:29:46 +0200 Subject: [PATCH] profile: move axes to ProfileScene Part of separating the static (for printing, export) and dynamic (UI) parts of the profile. This is still quite messy with many direct accesses from the ProfileWidget. Signed-off-by: Berthold Stoeger --- profile-widget/divecartesianaxis.cpp | 44 ++- profile-widget/divecartesianaxis.h | 11 +- profile-widget/divehandler.cpp | 3 +- profile-widget/profilescene.cpp | 284 ++++++++++++++++- profile-widget/profilescene.h | 31 +- profile-widget/profilewidget2.cpp | 439 ++++++--------------------- profile-widget/profilewidget2.h | 16 - 7 files changed, 430 insertions(+), 398 deletions(-) diff --git a/profile-widget/divecartesianaxis.cpp b/profile-widget/divecartesianaxis.cpp index c048a3a17..1f6f5a81f 100644 --- a/profile-widget/divecartesianaxis.cpp +++ b/profile-widget/divecartesianaxis.cpp @@ -7,7 +7,7 @@ #include "qt-models/diveplotdatamodel.h" #include "profile-widget/animationfunctions.h" #include "profile-widget/divelineitem.h" -#include "profile-widget/profilewidget2.h" +#include "profile-widget/profilescene.h" QPen DiveCartesianAxis::gridPen() const { @@ -60,10 +60,10 @@ void DiveCartesianAxis::setTextColor(const QColor &color) textColor = color; } -DiveCartesianAxis::DiveCartesianAxis(double fontPrintScale, ProfileWidget2 *widget) : QObject(), +DiveCartesianAxis::DiveCartesianAxis(double fontPrintScale, ProfileScene &scene) : QObject(), QGraphicsLineItem(), printMode(false), - profileWidget(widget), + scene(scene), orientation(LeftToRight), min(0), max(0), @@ -133,11 +133,9 @@ void emptyList(QList &list, int steps, int speed) void DiveCartesianAxis::updateTicks(color_index_t color) { - if (!scene() || (!changed && !printMode)) + if (!changed && !printMode) return; QLineF m = line(); - // unused so far: - // QGraphicsView *view = scene()->views().first(); double stepsInRange = (max - min) / interval; int steps = (int)stepsInRange; double currValueText = min; @@ -146,8 +144,8 @@ void DiveCartesianAxis::updateTicks(color_index_t color) if (steps < 1) return; - emptyList(labels, steps, profileWidget->animSpeed); - emptyList(lines, steps, profileWidget->animSpeed); + emptyList(labels, steps, scene.animSpeed); + emptyList(lines, steps, scene.animSpeed); // Move the remaining ticks / text to their correct positions // regarding the possible new values for the axis @@ -174,9 +172,9 @@ void DiveCartesianAxis::updateTicks(color_index_t color) labels[i]->setText(textForValue(currValueText)); if (orientation == LeftToRight || orientation == RightToLeft) { - Animations::moveTo(labels[i], profileWidget->animSpeed, childPos, m.y1() + tick_size); + Animations::moveTo(labels[i], scene.animSpeed, childPos, m.y1() + tick_size); } else { - Animations::moveTo(labels[i], profileWidget->animSpeed ,m.x1() - tick_size, childPos); + Animations::moveTo(labels[i], scene.animSpeed ,m.x1() - tick_size, childPos); } } @@ -186,9 +184,9 @@ void DiveCartesianAxis::updateTicks(color_index_t color) begin - i * stepSize; if (orientation == LeftToRight || orientation == RightToLeft) { - Animations::moveTo(lines[i], profileWidget->animSpeed, childPos, m.y1()); + Animations::moveTo(lines[i], scene.animSpeed, childPos, m.y1()); } else { - Animations::moveTo(lines[i], profileWidget->animSpeed, m.x1(), childPos); + Animations::moveTo(lines[i], scene.animSpeed, m.x1(), childPos); } } @@ -208,12 +206,12 @@ void DiveCartesianAxis::updateTicks(color_index_t color) labels.push_back(label); if (orientation == RightToLeft || orientation == LeftToRight) { label->setAlignment(Qt::AlignBottom | Qt::AlignHCenter); - label->setPos(scene()->sceneRect().width() + 10, m.y1() + tick_size); // position it outside of the scene); - Animations::moveTo(label, profileWidget->animSpeed,childPos , m.y1() + tick_size); + label->setPos(scene.sceneRect().width() + 10, m.y1() + tick_size); // position it outside of the scene; + Animations::moveTo(label, scene.animSpeed,childPos , m.y1() + tick_size); } else { label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); - label->setPos(m.x1() - tick_size, scene()->sceneRect().height() + 10); - Animations::moveTo(label, profileWidget->animSpeed, m.x1() - tick_size, childPos); + label->setPos(m.x1() - tick_size, scene.sceneRect().height() + 10); + Animations::moveTo(label, scene.animSpeed, m.x1() - tick_size, childPos); } } @@ -233,14 +231,14 @@ void DiveCartesianAxis::updateTicks(color_index_t color) lines.push_back(line); if (orientation == RightToLeft || orientation == LeftToRight) { line->setLine(0, -line_size, 0, 0); - line->setPos(scene()->sceneRect().width() + 10, m.y1()); // position it outside of the scene); - Animations::moveTo(line, profileWidget->animSpeed, childPos, m.y1()); + line->setPos(scene.sceneRect().width() + 10, m.y1()); // position it outside of the scene); + Animations::moveTo(line, scene.animSpeed, childPos, m.y1()); } else { QPointF p1 = mapFromScene(3, 0); QPointF p2 = mapFromScene(line_size, 0); line->setLine(p1.x(), 0, p2.x(), 0); - line->setPos(m.x1(), scene()->sceneRect().height() + 10); - Animations::moveTo(line, profileWidget->animSpeed, m.x1(), childPos); + line->setPos(m.x1(), scene.sceneRect().height() + 10); + Animations::moveTo(line, scene.animSpeed, m.x1(), childPos); } } @@ -355,7 +353,7 @@ QColor DepthAxis::colorForValue(double) const return QColor(Qt::red); } -DepthAxis::DepthAxis(double fontPrintScale, ProfileWidget2 *widget) : DiveCartesianAxis(fontPrintScale, widget), +DepthAxis::DepthAxis(double fontPrintScale, ProfileScene &scene) : DiveCartesianAxis(fontPrintScale, scene), unitSystem(prefs.units.length) { connect(&diveListNotifier, &DiveListNotifier::settingsChanged, this, &DepthAxis::settingsChanged); @@ -399,8 +397,8 @@ QString TemperatureAxis::textForValue(double value) const return QString::number(mkelvin_to_C((int)value)); } -PartialGasPressureAxis::PartialGasPressureAxis(const DivePlotDataModel &model, double fontPrintScale, ProfileWidget2 *widget) : - DiveCartesianAxis(fontPrintScale, widget), +PartialGasPressureAxis::PartialGasPressureAxis(const DivePlotDataModel &model, double fontPrintScale, ProfileScene &scene) : + DiveCartesianAxis(fontPrintScale, scene), model(model) { connect(&diveListNotifier, &DiveListNotifier::settingsChanged, this, &PartialGasPressureAxis::update); diff --git a/profile-widget/divecartesianaxis.h b/profile-widget/divecartesianaxis.h index ecd46cbd0..253f4e467 100644 --- a/profile-widget/divecartesianaxis.h +++ b/profile-widget/divecartesianaxis.h @@ -5,8 +5,9 @@ #include #include #include "core/color.h" -#include "profilewidget2.h" +#include "core/units.h" +class ProfileScene; class QPropertyAnimation; class DiveTextItem; class DiveLineItem; @@ -28,7 +29,7 @@ public: LeftToRight, RightToLeft }; - DiveCartesianAxis(double fontPrintScale, ProfileWidget2 *widget); + DiveCartesianAxis(double fontPrintScale, ProfileScene &scene); ~DiveCartesianAxis(); void setPrintMode(bool mode); void setMinimum(double minimum); @@ -54,7 +55,7 @@ signals: void sizeChanged(); protected: - ProfileWidget2 *profileWidget; + ProfileScene &scene; virtual QString textForValue(double value) const; virtual QColor colorForValue(double value) const; Orientation orientation; @@ -76,7 +77,7 @@ protected: class DepthAxis : public DiveCartesianAxis { Q_OBJECT public: - DepthAxis(double fontPrintScale, ProfileWidget2 *widget); + DepthAxis(double fontPrintScale, ProfileScene &scene); private: QString textForValue(double value) const override; QColor colorForValue(double value) const override; @@ -107,7 +108,7 @@ private: class PartialGasPressureAxis : public DiveCartesianAxis { Q_OBJECT public: - PartialGasPressureAxis(const DivePlotDataModel &model, double fontPrintScale, ProfileWidget2 *widget); + PartialGasPressureAxis(const DivePlotDataModel &model, double fontPrintScale, ProfileScene &scene); public slots: void update(); diff --git a/profile-widget/divehandler.cpp b/profile-widget/divehandler.cpp index 2f06ea661..28ac90ffe 100644 --- a/profile-widget/divehandler.cpp +++ b/profile-widget/divehandler.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "divehandler.h" #include "profilewidget2.h" +#include "profilescene.h" #include "core/dive.h" #include "core/gettextfromc.h" #include "core/qthelper.h" @@ -74,7 +75,7 @@ void DiveHandler::mouseMoveEvent(QGraphicsSceneMouseEvent *event) t.start(); ProfileWidget2 *view = qobject_cast(scene()->views().first()); - if(view->isPointOutOfBoundaries(event->scenePos())) + if(view->profileScene->isPointOutOfBoundaries(event->scenePos())) return; QGraphicsEllipseItem::mouseMoveEvent(event); diff --git a/profile-widget/profilescene.cpp b/profile-widget/profilescene.cpp index 14ebc1299..3d2081064 100644 --- a/profile-widget/profilescene.cpp +++ b/profile-widget/profilescene.cpp @@ -1,12 +1,294 @@ // SPDX-License-Identifier: GPL-2.0 #include "profilescene.h" +#include "divecartesianaxis.h" +#include "core/pref.h" +#include "qt-models/diveplotdatamodel.h" -ProfileScene::ProfileScene() +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) : + 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)) { setSceneRect(0, 0, 100, 100); setItemIndexMethod(QGraphicsScene::NoIndex); + + // 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); } ProfileScene::~ProfileScene() { } + +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)); +} diff --git a/profile-widget/profilescene.h b/profile-widget/profilescene.h index 13d25700a..03dc61552 100644 --- a/profile-widget/profilescene.h +++ b/profile-widget/profilescene.h @@ -1,15 +1,38 @@ -// SPDX-License-Identifier: GPL-2.0 -// Displays the dive profile. Used by the interactive profile widget -// and the printing/exporting code. + // SPDX-License-Identifier: GPL-2.0 + // Displays the dive profile. Used by the interactive profile widget + // and the printing/exporting code. #ifndef PROFILESCENE_H #define PROFILESCENE_H #include +class DivePlotDataModel; + +class DepthAxis; +class DiveCartesianAxis; +class PartialGasPressureAxis; +class TemperatureAxis; +class TimeAxis; + class ProfileScene : public QGraphicsScene { public: - ProfileScene(); + ProfileScene(double fontPrintScale); ~ProfileScene(); + + void updateAxes(); // Update axes according to preferences + bool isPointOutOfBoundaries(const QPointF &point) const; + + int animSpeed; +private: + friend class ProfileWidget2; // For now, give the ProfileWidget full access to the objects on the scene + DivePlotDataModel *dataModel; + DepthAxis *profileYAxis; + PartialGasPressureAxis *gasYAxis; + TemperatureAxis *temperatureAxis; + TimeAxis *timeAxis; + DiveCartesianAxis *cylinderPressureAxis; + DiveCartesianAxis *heartBeatAxis; + DiveCartesianAxis *percentageAxis; }; #endif diff --git a/profile-widget/profilewidget2.cpp b/profile-widget/profilewidget2.cpp index be26a5e50..dda0f0a29 100644 --- a/profile-widget/profilewidget2.cpp +++ b/profile-widget/profilewidget2.cpp @@ -42,8 +42,6 @@ #include #endif -#define PP_GRAPHS_ENABLED (prefs.pp_graphs.po2 || prefs.pp_graphs.pn2 || prefs.pp_graphs.phe) - /* This is the global 'Item position' variable. * it should tell you where to position things up * on the canvas. @@ -57,26 +55,8 @@ const static struct ItemPos { QPointF on; QPointF off; }; - struct Axis { - Pos pos; - QLineF shrinked; - QLineF expanded; - QLineF intermediate; - }; Pos dcLabel; Pos tankBar; - Axis depth; - Axis partialPressure; - Axis partialPressureTissue; - Axis partialPressureWithTankBar; - Axis percentage; - Axis percentageWithTankBar; - Axis time; - Axis cylinder; - Axis temperature; - Axis temperatureAll; - Axis heartBeat; - Axis heartBeatWithTankBar; ItemPos(); } itemPos; @@ -89,7 +69,7 @@ static const double thumbnailBaseZValue = 100.0; template T *ProfileWidget2::createItem(const DiveCartesianAxis &vAxis, int vColumn, int z, Args&&... args) { - T *res = new T(*dataModel, *timeAxis, DivePlotDataModel::TIME, vAxis, vColumn, + T *res = new T(*profileScene->dataModel, *profileScene->timeAxis, DivePlotDataModel::TIME, vAxis, vColumn, std::forward(args)...); res->setZValue(static_cast(z)); profileItems.push_back(res); @@ -97,9 +77,8 @@ T *ProfileWidget2::createItem(const DiveCartesianAxis &vAxis, int vColumn, int z } ProfileWidget2::ProfileWidget2(DivePlannerPointsModel *plannerModelIn, double fontPrintScale, QWidget *parent) : QGraphicsView(parent), - profileScene(new ProfileScene), + profileScene(new ProfileScene(fontPrintScale)), currentState(INVALID), - dataModel(new DivePlotDataModel(this)), plannerModel(plannerModelIn), zoomLevel(0), zoomFactor(1.15), @@ -110,17 +89,12 @@ ProfileWidget2::ProfileWidget2(DivePlannerPointsModel *plannerModelIn, double fo #ifndef SUBSURFACE_MOBILE toolTipItem(new ToolTipItem()), #endif - profileYAxis(new DepthAxis(fontPrintScale, this)), - gasYAxis(new PartialGasPressureAxis(*dataModel, fontPrintScale, this)), - temperatureAxis(new TemperatureAxis(fontPrintScale, this)), - timeAxis(new TimeAxis(fontPrintScale, this)), - diveProfileItem(createItem(*profileYAxis, DivePlotDataModel::DEPTH, 0, fontPrintScale)), - temperatureItem(createItem(*temperatureAxis, DivePlotDataModel::TEMPERATURE, 1, fontPrintScale)), - meanDepthItem(createItem(*profileYAxis, DivePlotDataModel::INSTANT_MEANDEPTH, 1, fontPrintScale)), - cylinderPressureAxis(new DiveCartesianAxis(fontPrintScale, this)), - gasPressureItem(createItem(*cylinderPressureAxis, DivePlotDataModel::TEMPERATURE, 1, fontPrintScale)), + diveProfileItem(createItem(*profileScene->profileYAxis, DivePlotDataModel::DEPTH, 0, fontPrintScale)), + temperatureItem(createItem(*profileScene->temperatureAxis, DivePlotDataModel::TEMPERATURE, 1, fontPrintScale)), + meanDepthItem(createItem(*profileScene->profileYAxis, DivePlotDataModel::INSTANT_MEANDEPTH, 1, fontPrintScale)), + gasPressureItem(createItem(*profileScene->cylinderPressureAxis, DivePlotDataModel::TEMPERATURE, 1, fontPrintScale)), diveComputerText(new DiveTextItem(fontPrintScale)), - reportedCeiling(createItem(*profileYAxis, DivePlotDataModel::CEILING, 1, fontPrintScale)), + reportedCeiling(createItem(*profileScene->profileYAxis, DivePlotDataModel::CEILING, 1, fontPrintScale)), pn2GasItem(createPPGas(DivePlotDataModel::PN2, PN2, PN2_ALERT, NULL, &prefs.pp_graphs.pn2_threshold)), pheGasItem(createPPGas(DivePlotDataModel::PHE, PHE, PHE_ALERT, NULL, &prefs.pp_graphs.phe_threshold)), po2GasItem(createPPGas(DivePlotDataModel::PO2, PO2, PO2_ALERT, &prefs.pp_graphs.po2_threshold_min, &prefs.pp_graphs.po2_threshold_max)), @@ -129,17 +103,15 @@ ProfileWidget2::ProfileWidget2(DivePlannerPointsModel *plannerModelIn, double fo ccrsensor2GasItem(createPPGas(DivePlotDataModel::CCRSENSOR2, CCRSENSOR2, PO2_ALERT, &prefs.pp_graphs.po2_threshold_min, &prefs.pp_graphs.po2_threshold_max)), ccrsensor3GasItem(createPPGas(DivePlotDataModel::CCRSENSOR3, CCRSENSOR3, PO2_ALERT, &prefs.pp_graphs.po2_threshold_min, &prefs.pp_graphs.po2_threshold_max)), ocpo2GasItem(createPPGas(DivePlotDataModel::SCR_OC_PO2, SCR_OCPO2, PO2_ALERT, &prefs.pp_graphs.po2_threshold_min, &prefs.pp_graphs.po2_threshold_max)), - diveCeiling(createItem(*profileYAxis, DivePlotDataModel::CEILING, 1, fontPrintScale)), + diveCeiling(createItem(*profileScene->profileYAxis, DivePlotDataModel::CEILING, 1, fontPrintScale)), decoModelParameters(new DiveTextItem(fontPrintScale)), #ifndef SUBSURFACE_MOBILE - heartBeatAxis(new DiveCartesianAxis(fontPrintScale, this)), - heartBeatItem(createItem(*heartBeatAxis, DivePlotDataModel::HEARTBEAT, 1, fontPrintScale)), - percentageAxis(new DiveCartesianAxis(fontPrintScale, this)), + heartBeatItem(createItem(*profileScene->heartBeatAxis, DivePlotDataModel::HEARTBEAT, 1, fontPrintScale)), mouseFollowerVertical(new DiveLineItem()), mouseFollowerHorizontal(new DiveLineItem()), rulerItem(new RulerItem2()), #endif - tankItem(new TankItem(*timeAxis, fontPrintScale)), + tankItem(new TankItem(*profileScene->timeAxis, fontPrintScale)), shouldCalculateMax(true), fontPrintScale(fontPrintScale) { @@ -171,7 +143,7 @@ ProfileWidget2::ProfileWidget2(DivePlannerPointsModel *plannerModelIn, double fo #if !defined(QT_NO_DEBUG) && defined(SHOW_PLOT_INFO_TABLE) QTableView *diveDepthTableView = new QTableView(); - diveDepthTableView->setModel(dataModel); + diveDepthTableView->setModel(profileScene->dataModel); diveDepthTableView->show(); #endif @@ -219,18 +191,11 @@ void ProfileWidget2::addActionShortcut(const Qt::Key shortcut, void (ProfileWidg void ProfileWidget2::addItemsToScene() { scene()->addItem(background); - scene()->addItem(profileYAxis); - scene()->addItem(gasYAxis); - scene()->addItem(temperatureAxis); - scene()->addItem(timeAxis); - scene()->addItem(cylinderPressureAxis); scene()->addItem(diveComputerText); scene()->addItem(tankItem); scene()->addItem(decoModelParameters); #ifndef SUBSURFACE_MOBILE scene()->addItem(toolTipItem); - scene()->addItem(percentageAxis); - scene()->addItem(heartBeatAxis); scene()->addItem(rulerItem); scene()->addItem(rulerItem->sourceNode()); scene()->addItem(rulerItem->destNode()); @@ -250,55 +215,16 @@ void ProfileWidget2::setupItemOnScene() background->setZValue(9999); #ifndef SUBSURFACE_MOBILE toolTipItem->setZValue(9998); - toolTipItem->setTimeAxis(timeAxis); + toolTipItem->setTimeAxis(profileScene->timeAxis); rulerItem->setZValue(9997); #endif tankItem->setZValue(100); - 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); - - diveComputerText->setAlignment(Qt::AlignRight | Qt::AlignTop); diveComputerText->setBrush(getColor(TIME_TEXT, isGrayscale)); #ifndef SUBSURFACE_MOBILE - rulerItem->setAxis(timeAxis, profileYAxis); + rulerItem->setAxis(profileScene->timeAxis, profileScene->profileYAxis); #endif // show the deco model parameters at the top in the center decoModelParameters->setY(0); @@ -307,26 +233,12 @@ void ProfileWidget2::setupItemOnScene() decoModelParameters->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); #ifndef SUBSURFACE_MOBILE for (int i = 0; i < 16; i++) { - DiveCalculatedTissue *tissueItem = createItem(*profileYAxis, DivePlotDataModel::TISSUE_1 + i, i + 1, fontPrintScale); + DiveCalculatedTissue *tissueItem = createItem(*profileScene->profileYAxis, DivePlotDataModel::TISSUE_1 + i, i + 1, fontPrintScale); allTissues.append(tissueItem); - DivePercentageItem *percentageItem = createItem(*percentageAxis, DivePlotDataModel::PERCENTAGE_1 + i, i + 1, i, fontPrintScale); + DivePercentageItem *percentageItem = createItem(*profileScene->percentageAxis, DivePlotDataModel::PERCENTAGE_1 + i, i + 1, i, fontPrintScale); allPercentages.append(percentageItem); } #endif - -#ifndef SUBSURFACE_MOBILE - heartBeatAxis->setTextVisible(true); - heartBeatAxis->setLinesVisible(true); - percentageAxis->setTextVisible(true); - percentageAxis->setLinesVisible(true); -#endif - temperatureAxis->setTextVisible(false); - temperatureAxis->setLinesVisible(false); - cylinderPressureAxis->setTextVisible(false); - cylinderPressureAxis->setLinesVisible(false); - timeAxis->setLinesVisible(true); - profileYAxis->setLinesVisible(true); - gasYAxis->setZValue(timeAxis->zValue() + 1); } void ProfileWidget2::replot() @@ -337,7 +249,7 @@ void ProfileWidget2::replot() PartialPressureGasItem *ProfileWidget2::createPPGas(int column, color_index_t color, color_index_t colorAlert, const double *thresholdSettingsMin, const double *thresholdSettingsMax) { - PartialPressureGasItem *item = createItem(*gasYAxis, column, 99, fontPrintScale); + PartialPressureGasItem *item = createItem(*profileScene->gasYAxis, column, 99, fontPrintScale); item->setThresholdSettingsKey(thresholdSettingsMin, thresholdSettingsMax); item->setColors(getColor(color, isGrayscale), getColor(colorAlert, isGrayscale)); return item; @@ -352,104 +264,6 @@ ItemPos::ItemPos() * Axis and everything else is auto-adjusted.* */ - //Depth Axis Config - depth.pos.on.setX(3); - depth.pos.on.setY(3); - depth.pos.off.setX(-2); - depth.pos.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.pos.on.setX(3); -#ifndef SUBSURFACE_MOBILE - time.pos.on.setY(95); -#else - time.pos.on.setY(89.5); -#endif - time.pos.off.setX(3); - time.pos.off.setY(110); - time.expanded.setP1(QPointF(0, 0)); - time.expanded.setP2(QPointF(94, 0)); - - // Partial Gas Axis Config - partialPressure.pos.on.setX(97); -#ifndef SUBSURFACE_MOBILE - partialPressure.pos.on.setY(75); -#else - partialPressure.pos.on.setY(70); -#endif - partialPressure.pos.off.setX(110); - partialPressure.pos.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.pos.on.setX(97); - partialPressureTissue.pos.on.setY(65); - partialPressureTissue.expanded.setP2(QPointF(0, 16)); - - // cylinder axis config - cylinder.pos.on.setX(3); - cylinder.pos.on.setY(20); - cylinder.pos.off.setX(-10); - cylinder.pos.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.pos.on.setX(3); - temperature.pos.off.setX(-10); - temperature.pos.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.pos.on.setY(60); - temperatureAll.pos.on.setY(51); - temperature.intermediate.setP1(QPointF(0, 2)); - temperature.intermediate.setP2(QPointF(0, 12)); -#else - temperature.pos.on.setY(51); - temperatureAll.pos.on.setY(47); - temperature.intermediate.setP1(QPointF(0, 2)); - temperature.intermediate.setP2(QPointF(0, 12)); -#endif - - // Heart rate axis config - heartBeat.pos.on.setX(3); - heartBeat.pos.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.pos.on.setX(3); - percentage.pos.on.setY(80); - percentage.expanded.setP1(QPointF(0, 0)); - percentage.expanded.setP2(QPointF(0, 15)); - percentageWithTankBar = percentage; - percentageWithTankBar.expanded.setP2(QPointF(0, 11.9)); - dcLabel.on.setX(3); dcLabel.on.setY(100); dcLabel.off.setX(-10); @@ -521,7 +335,7 @@ void ProfileWidget2::plotDive(const struct dive *dIn, int dcIn, bool doClearPict } // special handling when switching from empty state - animSpeed = instant || currentState == EMPTY || printMode ? 0 : qPrefDisplay::animation_speed(); + profileScene->animSpeed = instant || currentState == EMPTY || printMode ? 0 : qPrefDisplay::animation_speed(); // restore default zoom level resetZoom(); @@ -577,17 +391,17 @@ void ProfileWidget2::plotDive(const struct dive *dIn, int dcIn, bool doClearPict maxdepth = newMaxDepth; } - dataModel->setDive(plotInfo); + profileScene->dataModel->setDive(plotInfo); #ifndef SUBSURFACE_MOBILE toolTipItem->setPlotInfo(plotInfo); #endif // It seems that I'll have a lot of boilerplate setting the model / axis for // each item, I'll mostly like to fix this in the future, but I'll keep at this for now. - profileYAxis->setMaximum(maxdepth); - profileYAxis->updateTicks(); + profileScene->profileYAxis->setMaximum(maxdepth); + profileScene->profileYAxis->updateTicks(); - temperatureAxis->setMinimum(plotInfo.mintemp); - temperatureAxis->setMaximum(plotInfo.maxtemp - plotInfo.mintemp > 2000 ? plotInfo.maxtemp : plotInfo.mintemp + 2000); + profileScene->temperatureAxis->setMinimum(plotInfo.mintemp); + profileScene->temperatureAxis->setMaximum(plotInfo.maxtemp - plotInfo.mintemp > 2000 ? plotInfo.maxtemp : plotInfo.mintemp + 2000); #ifndef SUBSURFACE_MOBILE if (plotInfo.maxhr) { @@ -602,20 +416,20 @@ void ProfileWidget2::plotDive(const struct dive *dIn, int dcIn, bool doClearPict else heartBeatAxisTick = 50; for (heartBeatAxisMax = heartBeatAxisMin; heartBeatAxisMax < plotInfo.maxhr; heartBeatAxisMax += heartBeatAxisTick); - heartBeatAxis->setMinimum(heartBeatAxisMin); - heartBeatAxis->setMaximum(heartBeatAxisMax + 1); - heartBeatAxis->setTickInterval(heartBeatAxisTick); - heartBeatAxis->updateTicks(HR_AXIS); // this shows the ticks + profileScene->heartBeatAxis->setMinimum(heartBeatAxisMin); + profileScene->heartBeatAxis->setMaximum(heartBeatAxisMax + 1); + profileScene->heartBeatAxis->setTickInterval(heartBeatAxisTick); + profileScene->heartBeatAxis->updateTicks(HR_AXIS); // this shows the ticks } - heartBeatAxis->setVisible(prefs.hrgraph && plotInfo.maxhr); + profileScene->heartBeatAxis->setVisible(prefs.hrgraph && plotInfo.maxhr); - percentageAxis->setMinimum(0); - percentageAxis->setMaximum(100); - percentageAxis->setVisible(false); - percentageAxis->updateTicks(HR_AXIS); + profileScene->percentageAxis->setMinimum(0); + profileScene->percentageAxis->setMaximum(100); + profileScene->percentageAxis->setVisible(false); + profileScene->percentageAxis->updateTicks(HR_AXIS); #endif if (shouldCalculateMax) - timeAxis->setMaximum(maxtime); + profileScene->timeAxis->setMaximum(maxtime); int i, incr; static int increments[8] = { 10, 20, 30, 60, 5 * 60, 10 * 60, 15 * 60, 30 * 60 }; /* Time markers: at most every 10 seconds, but no more than 12 markers. @@ -631,18 +445,18 @@ void ProfileWidget2::plotDive(const struct dive *dIn, int dcIn, bool doClearPict incr = increments[i]; while (maxtime / incr > 12) incr *= 2; - timeAxis->setTickInterval(incr); - timeAxis->updateTicks(); - cylinderPressureAxis->setMinimum(plotInfo.minpressure); - cylinderPressureAxis->setMaximum(plotInfo.maxpressure); + profileScene->timeAxis->setTickInterval(incr); + profileScene->timeAxis->updateTicks(); + profileScene->cylinderPressureAxis->setMinimum(plotInfo.minpressure); + profileScene->cylinderPressureAxis->setMaximum(plotInfo.maxpressure); #ifndef SUBSURFACE_MOBILE rulerItem->setPlotInfo(d, plotInfo); #endif #ifdef SUBSURFACE_MOBILE if (currentdc->divemode == CCR) { - gasYAxis->setPos(itemPos.partialPressure.pos.on); - gasYAxis->setLine(itemPos.partialPressure.expanded); + profileScene->gasYAxis->setPos(itemPos.partialPressure.pos.on); + profileScene->gasYAxis->setLine(itemPos.partialPressure.expanded); tankItem->setVisible(false); pn2GasItem->setVisible(false); @@ -665,7 +479,7 @@ void ProfileWidget2::plotDive(const struct dive *dIn, int dcIn, bool doClearPict temperatureItem->setVisible(false); } else { tankItem->setVisible(prefs.tankbar); - gasYAxis->setPos(itemPos.partialPressure.pos.off); + profileScene->gasYAxis->setPos(itemPos.partialPressure.pos.off); pn2GasItem->setVisible(false); po2GasItem->setVisible(false); pheGasItem->setVisible(false); @@ -678,7 +492,7 @@ void ProfileWidget2::plotDive(const struct dive *dIn, int dcIn, bool doClearPict #endif tankItem->setData(&plotInfo, d); - gasYAxis->update(); + profileScene->gasYAxis->update(); // Replot dive items for (AbstractProfilePolygonItem *item: profileItems) @@ -709,7 +523,9 @@ void ProfileWidget2::plotDive(const struct dive *dIn, int dcIn, bool doClearPict // printMode is always selected for SUBSURFACE_MOBILE due to font problems // BUT events are wanted. #endif - DiveEventItem *item = new DiveEventItem(d, event, lastgasmix, dataModel, timeAxis, profileYAxis, animSpeed, fontPrintScale); + DiveEventItem *item = new DiveEventItem(d, event, lastgasmix, profileScene->dataModel, + profileScene->timeAxis, profileScene->profileYAxis, profileScene->animSpeed, + fontPrintScale); item->setZValue(2); scene()->addItem(item); eventItems.push_back(item); @@ -775,67 +591,9 @@ void ProfileWidget2::actionRequestedReplot(bool) settingsChanged(); } -void ProfileWidget2::updateAxes() -{ -#ifndef SUBSURFACE_MOBILE - gasYAxis->update(); // Initialize ticks of partial pressure graph - if ((prefs.percentagegraph||prefs.hrgraph) && PP_GRAPHS_ENABLED) { - profileYAxis->animateChangeLine(itemPos.depth.shrinked); - temperatureAxis->setPos(itemPos.temperatureAll.pos.on); - temperatureAxis->animateChangeLine(itemPos.temperature.shrinked); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.shrinked); - - if (prefs.tankbar) { - percentageAxis->setPos(itemPos.percentageWithTankBar.pos.on); - percentageAxis->animateChangeLine(itemPos.percentageWithTankBar.expanded); - heartBeatAxis->setPos(itemPos.heartBeatWithTankBar.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeatWithTankBar.expanded); - } else { - percentageAxis->setPos(itemPos.percentage.pos.on); - percentageAxis->animateChangeLine(itemPos.percentage.expanded); - heartBeatAxis->setPos(itemPos.heartBeat.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeat.expanded); - } - gasYAxis->setPos(itemPos.partialPressureTissue.pos.on); - gasYAxis->animateChangeLine(itemPos.partialPressureTissue.expanded); - } else if (PP_GRAPHS_ENABLED || prefs.hrgraph || prefs.percentagegraph) { - profileYAxis->animateChangeLine(itemPos.depth.intermediate); - temperatureAxis->setPos(itemPos.temperature.pos.on); - temperatureAxis->animateChangeLine(itemPos.temperature.intermediate); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.intermediate); - if (prefs.tankbar) { - percentageAxis->setPos(itemPos.percentageWithTankBar.pos.on); - percentageAxis->animateChangeLine(itemPos.percentageWithTankBar.expanded); - gasYAxis->setPos(itemPos.partialPressureWithTankBar.pos.on); - gasYAxis->animateChangeLine(itemPos.partialPressureWithTankBar.expanded); - heartBeatAxis->setPos(itemPos.heartBeatWithTankBar.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeatWithTankBar.expanded); - } else { - gasYAxis->setPos(itemPos.partialPressure.pos.on); - gasYAxis->animateChangeLine(itemPos.partialPressure.expanded); - percentageAxis->setPos(itemPos.percentage.pos.on); - percentageAxis->animateChangeLine(itemPos.percentage.expanded); - heartBeatAxis->setPos(itemPos.heartBeat.pos.on); - heartBeatAxis->animateChangeLine(itemPos.heartBeat.expanded); - } - } else { -#else - { -#endif - profileYAxis->animateChangeLine(itemPos.depth.expanded); - if (prefs.tankbar) { - temperatureAxis->setPos(itemPos.temperatureAll.pos.on); - } else { - temperatureAxis->setPos(itemPos.temperature.pos.on); - } - temperatureAxis->animateChangeLine(itemPos.temperature.expanded); - cylinderPressureAxis->animateChangeLine(itemPos.cylinder.expanded); - } -} - void ProfileWidget2::settingsChanged() { - updateAxes(); + profileScene->updateAxes(); tankItem->setVisible(prefs.tankbar); replot(); } @@ -912,16 +670,6 @@ void ProfileWidget2::scale(qreal sx, qreal sy) #endif } -bool ProfileWidget2::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(); -} - #ifndef SUBSURFACE_MOBILE void ProfileWidget2::wheelEvent(QWheelEvent *event) { @@ -950,11 +698,11 @@ void ProfileWidget2::mouseDoubleClickEvent(QMouseEvent *event) { if ((currentState == PLAN || currentState == EDIT) && plannerModel) { QPointF mappedPos = mapToScene(event->pos()); - if (isPointOutOfBoundaries(mappedPos)) + if (profileScene->isPointOutOfBoundaries(mappedPos)) return; - int minutes = lrint(timeAxis->valueAt(mappedPos) / 60); - int milimeters = lrint(profileYAxis->valueAt(mappedPos) / M_OR_FT(1, 1)) * M_OR_FT(1, 1); + int minutes = lrint(profileScene->timeAxis->valueAt(mappedPos) / 60); + int milimeters = lrint(profileScene->profileYAxis->valueAt(mappedPos) / M_OR_FT(1, 1)) * M_OR_FT(1, 1); plannerModel->addStop(milimeters, minutes * 60); } } @@ -986,14 +734,14 @@ void ProfileWidget2::mouseMoveEvent(QMouseEvent *event) toolTipItem->setPos(mapToScene(toolTipPos)); } - qreal vValue = profileYAxis->valueAt(pos); - qreal hValue = timeAxis->valueAt(pos); + qreal vValue = profileScene->profileYAxis->valueAt(pos); + qreal hValue = profileScene->timeAxis->valueAt(pos); - if (profileYAxis->maximum() >= vValue && profileYAxis->minimum() <= vValue) { - mouseFollowerHorizontal->setPos(timeAxis->pos().x(), pos.y()); + if (profileScene->profileYAxis->maximum() >= vValue && profileScene->profileYAxis->minimum() <= vValue) { + mouseFollowerHorizontal->setPos(profileScene->timeAxis->pos().x(), pos.y()); } - if (timeAxis->maximum() >= hValue && timeAxis->minimum() <= hValue) { - mouseFollowerVertical->setPos(pos.x(), profileYAxis->line().y1()); + if (profileScene->timeAxis->maximum() >= hValue && profileScene->timeAxis->minimum() <= hValue) { + mouseFollowerVertical->setPos(pos.x(), profileScene->profileYAxis->line().y1()); } } @@ -1026,17 +774,17 @@ void ProfileWidget2::setEmptyState() #endif disconnectTemporaryConnections(); setBackgroundBrush(getColor(::BACKGROUND, isGrayscale)); - dataModel->clear(); + profileScene->dataModel->clear(); currentState = EMPTY; fixBackgroundPos(); background->setVisible(true); - profileYAxis->setVisible(false); - gasYAxis->setVisible(false); - timeAxis->setVisible(false); - temperatureAxis->setVisible(false); - cylinderPressureAxis->setVisible(false); + profileScene->profileYAxis->setVisible(false); + profileScene->gasYAxis->setVisible(false); + profileScene->timeAxis->setVisible(false); + profileScene->temperatureAxis->setVisible(false); + profileScene->cylinderPressureAxis->setVisible(false); diveComputerText->setVisible(false); reportedCeiling->setVisible(false); tankItem->setVisible(false); @@ -1056,7 +804,7 @@ void ProfileWidget2::setEmptyState() rulerItem->setVisible(false); mouseFollowerHorizontal->setVisible(false); mouseFollowerVertical->setVisible(false); - heartBeatAxis->setVisible(false); + profileScene->heartBeatAxis->setVisible(false); heartBeatItem->setVisible(false); #endif for (AbstractProfilePolygonItem *item: profileItems) @@ -1128,24 +876,19 @@ void ProfileWidget2::setProfileState() setBackgroundBrush(getColor(::BACKGROUND, isGrayscale)); background->setVisible(false); - profileYAxis->setVisible(true); - gasYAxis->setVisible(true); - timeAxis->setVisible(true); - temperatureAxis->setVisible(true); - cylinderPressureAxis->setVisible(true); + profileScene->profileYAxis->setVisible(true); + profileScene->gasYAxis->setVisible(true); + profileScene->timeAxis->setVisible(true); + profileScene->temperatureAxis->setVisible(true); + profileScene->cylinderPressureAxis->setVisible(true); - profileYAxis->setPos(itemPos.depth.pos.on); - updateAxes(); + profileScene->updateAxes(); #ifndef SUBSURFACE_MOBILE toolTipItem->readPos(); toolTipItem->setVisible(true); rulerItem->setVisible(prefs.rulergraph); #endif - timeAxis->setPos(itemPos.time.pos.on); - timeAxis->setLine(itemPos.time.expanded); - - cylinderPressureAxis->setPos(itemPos.cylinder.pos.on); diveComputerText->setVisible(true); diveComputerText->setPos(itemPos.dcLabel.on); @@ -1179,8 +922,8 @@ void ProfileWidget2::setEditState(const dive *d, int dc) setProfileState(d, dc); mouseFollowerHorizontal->setVisible(true); mouseFollowerVertical->setVisible(true); - mouseFollowerHorizontal->setLine(timeAxis->line()); - mouseFollowerVertical->setLine(QLineF(0, profileYAxis->pos().y(), 0, timeAxis->pos().y())); + mouseFollowerHorizontal->setLine(profileScene->timeAxis->line()); + mouseFollowerVertical->setLine(QLineF(0, profileScene->profileYAxis->pos().y(), 0, profileScene->timeAxis->pos().y())); disconnectTemporaryConnections(); actionsForKeys[Qt::Key_Left]->setShortcut(Qt::Key_Left); actionsForKeys[Qt::Key_Right]->setShortcut(Qt::Key_Right); @@ -1209,8 +952,8 @@ void ProfileWidget2::setPlanState(const dive *d, int dc) setProfileState(d, dc); mouseFollowerHorizontal->setVisible(true); mouseFollowerVertical->setVisible(true); - mouseFollowerHorizontal->setLine(timeAxis->line()); - mouseFollowerVertical->setLine(QLineF(0, profileYAxis->pos().y(), 0, timeAxis->pos().y())); + mouseFollowerHorizontal->setLine(profileScene->timeAxis->line()); + mouseFollowerVertical->setLine(QLineF(0, profileScene->profileYAxis->pos().y(), 0, profileScene->timeAxis->pos().y())); disconnectTemporaryConnections(); actionsForKeys[Qt::Key_Left]->setShortcut(Qt::Key_Left); actionsForKeys[Qt::Key_Right]->setShortcut(Qt::Key_Right); @@ -1306,7 +1049,7 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event) // create the profile context menu QPointF scenePos = mapToScene(mapFromGlobal(event->globalPos())); - qreal sec_val = timeAxis->valueAt(scenePos); + qreal sec_val = profileScene->timeAxis->valueAt(scenePos); int seconds = (sec_val < 0.0) ? 0 : (int)sec_val; DiveEventItem *item = dynamic_cast(sceneItem); @@ -1525,15 +1268,15 @@ void ProfileWidget2::setPrintMode(bool mode, bool grayscale) resetZoom(); // set printMode for axes - profileYAxis->setPrintMode(mode); - gasYAxis->setPrintMode(mode); - temperatureAxis->setPrintMode(mode); - timeAxis->setPrintMode(mode); - cylinderPressureAxis->setPrintMode(mode); + profileScene->profileYAxis->setPrintMode(mode); + profileScene->gasYAxis->setPrintMode(mode); + profileScene->temperatureAxis->setPrintMode(mode); + profileScene->timeAxis->setPrintMode(mode); + profileScene->cylinderPressureAxis->setPrintMode(mode); isGrayscale = mode ? grayscale : false; #ifndef SUBSURFACE_MOBILE - heartBeatAxis->setPrintMode(mode); - percentageAxis->setPrintMode(mode); + profileScene->heartBeatAxis->setPrintMode(mode); + profileScene->percentageAxis->setPrintMode(mode); mouseFollowerHorizontal->setVisible(!mode); mouseFollowerVertical->setVisible(!mode); @@ -1662,16 +1405,16 @@ void ProfileWidget2::repositionDiveHandlers() continue; DiveHandler *h = handles[i].get(); h->setVisible(datapoint.entered); - h->setPos(timeAxis->posAtValue(datapoint.time), profileYAxis->posAtValue(datapoint.depth.mm)); + h->setPos(profileScene->timeAxis->posAtValue(datapoint.time), profileScene->profileYAxis->posAtValue(datapoint.depth.mm)); QPointF p1; if (i == 0) { if (prefs.drop_stone_mode) // place the text on the straight line from the drop to stone position - p1 = QPointF(timeAxis->posAtValue(datapoint.depth.mm / prefs.descrate), - profileYAxis->posAtValue(datapoint.depth.mm)); + p1 = QPointF(profileScene->timeAxis->posAtValue(datapoint.depth.mm / prefs.descrate), + profileScene->profileYAxis->posAtValue(datapoint.depth.mm)); else // place the text on the straight line from the origin to the first position - p1 = QPointF(timeAxis->posAtValue(0), profileYAxis->posAtValue(0)); + p1 = QPointF(profileScene->timeAxis->posAtValue(0), profileScene->profileYAxis->posAtValue(0)); } else { // place the text on the line from the last position p1 = handles[i - 1]->pos(); @@ -1695,13 +1438,13 @@ void ProfileWidget2::divePlannerHandlerMoved() int index = handleIndex(activeHandler); // Grow the time axis if necessary. - int minutes = lrint(timeAxis->valueAt(activeHandler->pos()) / 60); - if (minutes * 60 > timeAxis->maximum() * 0.9) - timeAxis->setMaximum(timeAxis->maximum() * 1.02); + int minutes = lrint(profileScene->timeAxis->valueAt(activeHandler->pos()) / 60); + if (minutes * 60 > profileScene->timeAxis->maximum() * 0.9) + profileScene->timeAxis->setMaximum(profileScene->timeAxis->maximum() * 1.02); divedatapoint data = plannerModel->at(index); - data.depth.mm = lrint(profileYAxis->valueAt(activeHandler->pos()) / M_OR_FT(1, 1)) * M_OR_FT(1, 1); - data.time = lrint(timeAxis->valueAt(activeHandler->pos())); + data.depth.mm = lrint(profileScene->profileYAxis->valueAt(activeHandler->pos()) / M_OR_FT(1, 1)) * M_OR_FT(1, 1); + data.time = lrint(profileScene->timeAxis->valueAt(activeHandler->pos())); plannerModel->editStop(index, data); } @@ -1819,8 +1562,8 @@ void ProfileWidget2::updateDurationLine(PictureEntry &e) { if (e.duration.seconds > 0) { // We know the duration of this video, reset the line symbolizing its extent accordingly - double begin = timeAxis->posAtValue(e.offset.seconds); - double end = timeAxis->posAtValue(e.offset.seconds + e.duration.seconds); + double begin = profileScene->timeAxis->posAtValue(e.offset.seconds); + double end = profileScene->timeAxis->posAtValue(e.offset.seconds + e.duration.seconds); double y = e.thumbnail->y(); // Undo scaling for pen-width and line-width. For this purpose, we use the scaling of the y-axis. @@ -1935,7 +1678,7 @@ void ProfileWidget2::updateThumbnailXPos(PictureEntry &e) { // Here, we only set the x-coordinate of the picture. The y-coordinate // will be set later in calculatePictureYPositions(). - double x = timeAxis->posAtValue(e.offset.seconds); + double x = profileScene->timeAxis->posAtValue(e.offset.seconds); e.thumbnail->setX(x); } @@ -2028,7 +1771,7 @@ void ProfileWidget2::dropEvent(QDropEvent *event) QString filename; dataStream >> filename; QPointF mappedPos = mapToScene(event->pos()); - offset_t offset { (int32_t)lrint(timeAxis->valueAt(mappedPos)) }; + offset_t offset { (int32_t)lrint(profileScene->timeAxis->valueAt(mappedPos)) }; Command::setPictureOffset(mutable_dive(), filename, offset); if (event->source() == this) { diff --git a/profile-widget/profilewidget2.h b/profile-widget/profilewidget2.h index 515de6660..104d4e915 100644 --- a/profile-widget/profilewidget2.h +++ b/profile-widget/profilewidget2.h @@ -31,23 +31,18 @@ struct plot_info; class ToolTipItem; class DiveReportedCeiling; class DiveTextItem; -class TemperatureAxis; class DiveEventItem; -class DivePlotDataModel; class DivePixmapItem; class DiveRectItem; -class DepthAxis; class DiveCartesianAxis; class DiveProfileItem; class DivePlannerPointsModel; -class TimeAxis; class DiveTemperatureItem; class DiveHeartrateItem; class DiveGasPressureItem; class DiveCalculatedCeiling; class DiveCalculatedTissue; class PartialPressureGasItem; -class PartialGasPressureAxis; class AbstractProfilePolygonItem; class TankItem; class DiveHandler; @@ -76,7 +71,6 @@ public: void setPlanState(const struct dive *d, int dc); void setEditState(const struct dive *d, int dc); void setPrintMode(bool mode, bool grayscale = false); - bool isPointOutOfBoundaries(const QPointF &point) const; bool isPlanner() const; void draw(QPainter *painter, const QRect &pos); QImage toImage(QSize size); @@ -85,7 +79,6 @@ public: #endif std::unique_ptr profileScene; State currentState; - int animSpeed; signals: void editCurrentDive(); @@ -126,7 +119,6 @@ slots: // Necessary to call from QAction's signals. private: void setProfileState(); // keep currently displayed dive - void updateAxes(); // Update axes according to preferences void updateVisibility(); // Update visibility of non-interactive chart features according to preferences void resizeEvent(QResizeEvent *event) override; #ifndef SUBSURFACE_MOBILE @@ -169,7 +161,6 @@ private: void splitCurrentDC(); void renameCurrentDC(); - DivePlotDataModel *dataModel; DivePlannerPointsModel *plannerModel; // If null, no planning supported. int zoomLevel; qreal zoomFactor; @@ -186,15 +177,10 @@ private: const struct dive *d; int dc; struct plot_info plotInfo; - DepthAxis *profileYAxis; - PartialGasPressureAxis *gasYAxis; - TemperatureAxis *temperatureAxis; - TimeAxis *timeAxis; std::vector profileItems; DiveProfileItem *diveProfileItem; DiveTemperatureItem *temperatureItem; DiveMeanDepthItem *meanDepthItem; - DiveCartesianAxis *cylinderPressureAxis; DiveGasPressureItem *gasPressureItem; QList eventItems; DiveTextItem *diveComputerText; @@ -211,9 +197,7 @@ private: DiveTextItem *decoModelParameters; #ifndef SUBSURFACE_MOBILE QList allTissues; - DiveCartesianAxis *heartBeatAxis; DiveHeartrateItem *heartBeatItem; - DiveCartesianAxis *percentageAxis; QList allPercentages; DiveLineItem *mouseFollowerVertical; DiveLineItem *mouseFollowerHorizontal;