mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
profile: render profile on desktop via QtQuick
This breaks all dynamic features, including animations, zooming tooltips, planner-handles, etc. They will have to be converted one-by-one to QtQuick, which will be a major pain, as the ProfileView is destroyed by Qt6 on reparenting. This means that the view cannot store any persistent state. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
7eecc85464
commit
75886dd4d6
25 changed files with 322 additions and 76 deletions
|
|
@ -24,6 +24,8 @@ set(SUBSURFACE_PROFILE_LIB_SRCS
|
|||
divetooltipitem.h
|
||||
profilescene.cpp
|
||||
profilescene.h
|
||||
profileview.cpp
|
||||
profileview.h
|
||||
tankitem.cpp
|
||||
tankitem.h
|
||||
)
|
||||
|
|
@ -38,8 +40,6 @@ set(SUBSURFACE_PROFILE_LIB_SRCS
|
|||
${SUBSURFACE_PROFILE_LIB_SRCS}
|
||||
divehandler.cpp
|
||||
divehandler.h
|
||||
profilewidget2.cpp
|
||||
profilewidget2.h
|
||||
ruleritem.cpp
|
||||
ruleritem.h
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "divehandler.h"
|
||||
#include "profilewidget2.h"
|
||||
#include "profilescene.h"
|
||||
#include "core/dive.h"
|
||||
#include "core/gettextfromc.h"
|
||||
|
|
@ -22,8 +21,9 @@ DiveHandler::DiveHandler(const struct dive *d, int currentDcNr) : dive(d), dcNr(
|
|||
|
||||
int DiveHandler::parentIndex()
|
||||
{
|
||||
ProfileWidget2 *view = qobject_cast<ProfileWidget2 *>(scene()->views().first());
|
||||
return view->handleIndex(this);
|
||||
//ProfileWidget2 *view = qobject_cast<ProfileWidget2 *>(scene()->views().first());
|
||||
//return view->handleIndex(this);
|
||||
return 0; // FIXME
|
||||
}
|
||||
|
||||
void DiveHandler::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
|
||||
|
|
@ -54,19 +54,17 @@ void DiveHandler::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
|
|||
|
||||
void DiveHandler::selfRemove()
|
||||
{
|
||||
#ifndef SUBSURFACE_MOBILE
|
||||
setSelected(true);
|
||||
ProfileWidget2 *view = qobject_cast<ProfileWidget2 *>(scene()->views().first());
|
||||
view->keyDeleteAction();
|
||||
#endif
|
||||
//ProfileWidget2 *view = qobject_cast<ProfileWidget2 *>(scene()->views().first());
|
||||
//view->keyDeleteAction();
|
||||
}
|
||||
|
||||
void DiveHandler::changeGas()
|
||||
{
|
||||
ProfileWidget2 *view = qobject_cast<ProfileWidget2 *>(scene()->views().first());
|
||||
QAction *action = qobject_cast<QAction *>(sender());
|
||||
//ProfileWidget2 *view = qobject_cast<ProfileWidget2 *>(scene()->views().first());
|
||||
//QAction *action = qobject_cast<QAction *>(sender());
|
||||
|
||||
view->changeGas(parentIndex(), action->data().toInt());
|
||||
//view->changeGas(parentIndex(), action->data().toInt());
|
||||
}
|
||||
|
||||
void DiveHandler::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
|
|
@ -75,9 +73,9 @@ void DiveHandler::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||
return;
|
||||
t.start();
|
||||
|
||||
ProfileWidget2 *view = qobject_cast<ProfileWidget2*>(scene()->views().first());
|
||||
if(!view->profileScene->pointOnProfile(event->scenePos()))
|
||||
return;
|
||||
//ProfileWidget2 *view = qobject_cast<ProfileWidget2*>(scene()->views().first());
|
||||
//if(!view->profileScene->pointOnProfile(event->scenePos()))
|
||||
//return;
|
||||
|
||||
QGraphicsEllipseItem::mouseMoveEvent(event);
|
||||
emit moved();
|
||||
|
|
|
|||
|
|
@ -3,13 +3,15 @@
|
|||
#include "profile-widget/divecartesianaxis.h"
|
||||
#include "profile-widget/divetextitem.h"
|
||||
#include "profile-widget/animationfunctions.h"
|
||||
#include "core/dive.h"
|
||||
#include "core/profile.h"
|
||||
#include "qt-models/diveplannermodel.h"
|
||||
#include "core/qthelper.h"
|
||||
#include "core/settings/qPrefTechnicalDetails.h"
|
||||
#include "core/settings/qPrefLog.h"
|
||||
#include "libdivecomputer/parser.h"
|
||||
#include "profile-widget/profilewidget2.h"
|
||||
#include "qt-models/diveplannermodel.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
AbstractProfilePolygonItem::AbstractProfilePolygonItem(const plot_info &pInfo, const DiveCartesianAxis &horizontal,
|
||||
const DiveCartesianAxis &vertical, DataAccessor accessor,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "divetextitem.h"
|
||||
#include "profilewidget2.h"
|
||||
#include "core/color.h"
|
||||
#include "core/errorhelper.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <cmath>
|
||||
#include <QApplication>
|
||||
#include <QBrush>
|
||||
#include <QPainter>
|
||||
|
||||
static const double outlineSize = 3.0;
|
||||
|
||||
|
|
|
|||
|
|
@ -465,6 +465,10 @@ void ProfileScene::plotDive(const struct dive *dIn, int dcIn, DivePlannerPointsM
|
|||
updateVisibility(hasHeartBeat, simplified);
|
||||
updateAxes(hasHeartBeat, simplified);
|
||||
|
||||
// When we found that we don't have enough place to draw, the state was set to empty.
|
||||
if (empty)
|
||||
return;
|
||||
|
||||
int newMaxtime = get_maxtime(plotInfo);
|
||||
if (calcMax || newMaxtime > maxtime)
|
||||
maxtime = newMaxtime;
|
||||
|
|
|
|||
134
profile-widget/profileview.cpp
Normal file
134
profile-widget/profileview.cpp
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "profileview.h"
|
||||
#include "profilescene.h"
|
||||
#include "zvalues.h"
|
||||
#include "core/dive.h"
|
||||
#include "core/errorhelper.h"
|
||||
#include "core/pref.h"
|
||||
#include "core/settings/qPrefTechnicalDetails.h"
|
||||
#include "qt-quick/chartitem.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
static double calcZoom(int zoomLevel)
|
||||
{
|
||||
// Base of exponential zoom function: one wheel-click will increase the zoom by 15%.
|
||||
constexpr double zoomFactor = 1.15;
|
||||
return zoomLevel == 0 ? 1.0 : pow(zoomFactor, zoomLevel);
|
||||
}
|
||||
|
||||
ProfileView::ProfileView(QQuickItem *parent) : ChartView(parent, ProfileZValue::Count),
|
||||
d(nullptr),
|
||||
dc(0),
|
||||
zoomLevel(0),
|
||||
zoomedPosition(0.0),
|
||||
empty(true),
|
||||
shouldCalculateMax(true),
|
||||
profileScene(std::make_unique<ProfileScene>(1.0, false, false))
|
||||
{
|
||||
setBackgroundColor(Qt::black);
|
||||
setFlag(ItemHasContents, true);
|
||||
|
||||
setAcceptHoverEvents(true);
|
||||
setAcceptedMouseButtons(Qt::LeftButton);
|
||||
}
|
||||
|
||||
ProfileView::ProfileView() : ProfileView(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ProfileView::~ProfileView()
|
||||
{
|
||||
}
|
||||
|
||||
void ProfileView::resetPointers()
|
||||
{
|
||||
profileItem.reset();
|
||||
}
|
||||
|
||||
void ProfileView::plotAreaChanged(const QSizeF &s)
|
||||
{
|
||||
if (!empty)
|
||||
plotDive(d, dc, RenderFlags::Instant);
|
||||
}
|
||||
|
||||
void ProfileView::clear()
|
||||
{
|
||||
//clearPictures();
|
||||
//disconnectPlannerConnections();
|
||||
profileScene->clear();
|
||||
//handles.clear();
|
||||
//gases.clear();
|
||||
empty = true;
|
||||
d = nullptr;
|
||||
dc = 0;
|
||||
}
|
||||
|
||||
void ProfileView::plotDive(const struct dive *dIn, int dcIn, int flags)
|
||||
{
|
||||
d = dIn;
|
||||
dc = dcIn;
|
||||
if (!d) {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// If there was no previously displayed dive, turn off animations
|
||||
if (empty)
|
||||
flags |= RenderFlags::Instant;
|
||||
empty = false;
|
||||
|
||||
// If Qt decided to destroy our canvas, recreate it
|
||||
if (!profileItem)
|
||||
profileItem = createChartItem<ChartGraphicsSceneItem>(ProfileZValue::Profile);
|
||||
|
||||
profileItem->setPos(QPointF(0.0, 0.0));
|
||||
|
||||
QElapsedTimer measureDuration; // let's measure how long this takes us (maybe we'll turn of TTL calculation later
|
||||
measureDuration.start();
|
||||
|
||||
//DivePlannerPointsModel *model = currentState == EDIT || currentState == PLAN ? plannerModel : nullptr;
|
||||
DivePlannerPointsModel *model = nullptr;
|
||||
bool inPlanner = flags & RenderFlags::PlanMode;
|
||||
|
||||
QColor backgroundColor = inPlanner ? QColor("#D7E3EF")
|
||||
: getColor(::BACKGROUND, false);
|
||||
|
||||
double zoom = calcZoom(zoomLevel);
|
||||
|
||||
profileScene->resize(size());
|
||||
profileScene->plotDive(d, dc, model, inPlanner, true, //flags & RenderFlags::Instant,
|
||||
flags & RenderFlags::DontRecalculatePlotInfo,
|
||||
shouldCalculateMax, zoom, zoomedPosition);
|
||||
profileItem->draw(size(), backgroundColor, *profileScene);
|
||||
|
||||
//rulerItem->setVisible(prefs.rulergraph && currentState != PLAN && currentState != EDIT);
|
||||
//toolTipItem->setPlotInfo(profileScene->plotInfo);
|
||||
//rulerItem->setPlotInfo(d, profileScene->plotInfo);
|
||||
|
||||
//if ((currentState == EDIT || currentState == PLAN) && plannerModel) {
|
||||
//repositionDiveHandlers();
|
||||
//plannerModel->deleteTemporaryPlan();
|
||||
//}
|
||||
|
||||
// On zoom / pan don't recreate the picture thumbnails, only change their position.
|
||||
//if (flags & RenderFlags::DontRecalculatePlotInfo)
|
||||
//updateThumbnails();
|
||||
//else
|
||||
//plotPicturesInternal(d, flags & RenderFlags::Instant);
|
||||
|
||||
//toolTipItem->refresh(d, mapToScene(mapFromGlobal(QCursor::pos())), currentState == PLAN);
|
||||
|
||||
update();
|
||||
|
||||
// OK, how long did this take us? Anything above the second is way too long,
|
||||
// so if we are calculation TTS / NDL then let's force that off.
|
||||
qint64 elapsedTime = measureDuration.elapsed();
|
||||
if (verbose)
|
||||
qDebug() << "Profile calculation for dive " << d->number << "took" << elapsedTime << "ms" << " -- calculated ceiling preference is" << prefs.calcceiling;
|
||||
if (elapsedTime > 1000 && prefs.calcndltts) {
|
||||
qPrefTechnicalDetails::set_calcndltts(false);
|
||||
report_error("%s", qPrintable(tr("Show NDL / TTS was disabled because of excessive processing time")));
|
||||
}
|
||||
}
|
||||
42
profile-widget/profileview.h
Normal file
42
profile-widget/profileview.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#ifndef PROFILE_VIEW_H
|
||||
#define PROFILE_VIEW_H
|
||||
|
||||
#include "qt-quick/chartview.h"
|
||||
#include <memory>
|
||||
|
||||
class ChartGraphicsSceneItem;
|
||||
class ProfileScene;
|
||||
|
||||
class ProfileView : public ChartView {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProfileView();
|
||||
ProfileView(QQuickItem *parent);
|
||||
~ProfileView();
|
||||
|
||||
struct RenderFlags {
|
||||
static constexpr int None = 0;
|
||||
static constexpr int Instant = 1 << 0;
|
||||
static constexpr int DontRecalculatePlotInfo = 1 << 1;
|
||||
static constexpr int EditMode = 1 << 2;
|
||||
static constexpr int PlanMode = 1 << 3;
|
||||
};
|
||||
|
||||
void plotDive(const struct dive *d, int dc, int flags = RenderFlags::None);
|
||||
void clear();
|
||||
private:
|
||||
const struct dive *d;
|
||||
int dc;
|
||||
int zoomLevel;
|
||||
double zoomedPosition; // Position when zoomed: 0.0 = beginning, 1.0 = end.
|
||||
bool empty; // No dive shown.
|
||||
bool shouldCalculateMax; // Calculate maximum time and depth (default). False when dragging handles.
|
||||
std::unique_ptr<ProfileScene> profileScene;
|
||||
ChartItemPtr<ChartGraphicsSceneItem> profileItem;
|
||||
|
||||
void plotAreaChanged(const QSizeF &size) override;
|
||||
void resetPointers() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "profile-widget/profilewidget2.h"
|
||||
#include "profile-widget/profilescene.h"
|
||||
#include "core/device.h"
|
||||
#include "core/event.h"
|
||||
|
|
@ -398,21 +397,6 @@ static void hideAll(const T &container)
|
|||
item->setVisible(false);
|
||||
}
|
||||
|
||||
void ProfileWidget2::clear()
|
||||
{
|
||||
currentState = INIT;
|
||||
#ifndef SUBSURFACE_MOBILE
|
||||
clearPictures();
|
||||
#endif
|
||||
disconnectPlannerModel();
|
||||
profileScene->clear();
|
||||
handles.clear();
|
||||
gases.clear();
|
||||
empty = true;
|
||||
d = nullptr;
|
||||
dc = 0;
|
||||
}
|
||||
|
||||
void ProfileWidget2::setProfileState(const dive *dIn, int dcIn)
|
||||
{
|
||||
d = dIn;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ public:
|
|||
#ifndef SUBSURFACE_MOBILE
|
||||
bool eventFilter(QObject *, QEvent *) override;
|
||||
#endif
|
||||
std::unique_ptr<ProfileScene> profileScene;
|
||||
State currentState;
|
||||
|
||||
signals:
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "profile-widget/ruleritem.h"
|
||||
#include "profile-widget/profilewidget2.h"
|
||||
#include "core/settings/qPrefTechnicalDetails.h"
|
||||
|
||||
#include <qgraphicssceneevent.h>
|
||||
|
||||
#include "core/profile.h"
|
||||
|
||||
#include <QFont>
|
||||
#include <QFontMetrics>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsSceneEvent>
|
||||
#include <QGraphicsView>
|
||||
|
||||
RulerNodeItem2::RulerNodeItem2() :
|
||||
pInfo(NULL),
|
||||
idx(-1),
|
||||
|
|
@ -77,18 +80,16 @@ RulerItem2::RulerItem2() : pInfo(NULL),
|
|||
textItemBack->setPen(QColor(Qt::white));
|
||||
textItemBack->setFlag(QGraphicsItem::ItemIgnoresTransformations);
|
||||
setPen(QPen(QColor(Qt::black), 0.0));
|
||||
#ifndef SUBSURFACE_MOBILE
|
||||
connect(qPrefTechnicalDetails::instance(), &qPrefTechnicalDetails::rulergraphChanged, this, &RulerItem2::settingsChanged);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RulerItem2::settingsChanged(bool value)
|
||||
{
|
||||
ProfileWidget2 *profWidget = NULL;
|
||||
if (scene() && scene()->views().count())
|
||||
profWidget = qobject_cast<ProfileWidget2 *>(scene()->views().first());
|
||||
//ProfileWidget2 *profWidget = NULL;
|
||||
//if (scene() && scene()->views().count())
|
||||
//profWidget = qobject_cast<ProfileWidget2 *>(scene()->views().first());
|
||||
|
||||
setVisible( (profWidget && profWidget->currentState == ProfileWidget2::PROFILE) ? value : false);
|
||||
//setVisible( (profWidget && profWidget->currentState == ProfileWidget2::PROFILE) ? value : false);
|
||||
}
|
||||
|
||||
void RulerItem2::recalculate()
|
||||
|
|
|
|||
19
profile-widget/zvalues.h
Normal file
19
profile-widget/zvalues.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Defines the z-values of features in the profile view.
|
||||
// Objects with higher z-values are painted on top of objects
|
||||
// with smaller z-values. For the same z-value objects are
|
||||
// drawn in order of addition to the scene.
|
||||
#ifndef PROFILE_ZVALUES_H
|
||||
#define PROFILE_ZVALUES_H
|
||||
|
||||
// Encapsulating an enum in a struct is stupid, but allows us
|
||||
// to not poison the namespace and yet autoconvert to int
|
||||
// (in constrast to enum class). enum is so broken!
|
||||
struct ProfileZValue {
|
||||
enum ZValues {
|
||||
Profile = 0,
|
||||
Count
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue