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:
Berthold Stoeger 2023-05-20 14:27:20 +02:00
parent 7eecc85464
commit 75886dd4d6
25 changed files with 322 additions and 76 deletions

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "profilewidget.h"
#include "profile-widget/profilewidget2.h"
#include "profile-widget/profileview.h"
#include "commands/command.h"
#include "core/color.h"
#include "core/event.h"
@ -14,6 +14,8 @@
#include <QToolBar>
#include <QHBoxLayout>
#include <QQmlEngine>
#include <QQuickWidget>
#include <QStackedWidget>
#include <QLabel>
@ -54,6 +56,7 @@ void EmptyView::resizeEvent(QResizeEvent *)
update();
}
static const QUrl urlProfileView = QUrl(QStringLiteral("qrc:/qml/profileview.qml"));
ProfileWidget::ProfileWidget() : d(nullptr), dc(0), placingCommand(false)
{
ui.setupUi(this);
@ -74,7 +77,10 @@ ProfileWidget::ProfileWidget() : d(nullptr), dc(0), placingCommand(false)
emptyView.reset(new EmptyView);
view.reset(new ProfileWidget2(DivePlannerPointsModel::instance(), 1.0, this));
viewWidget.reset(new QQuickWidget);
viewWidget->setSource(urlProfileView);
viewWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
QToolBar *toolBar = new QToolBar(this);
for (QAction *a: toolbarActions)
toolBar->addAction(a);
@ -83,7 +89,7 @@ ProfileWidget::ProfileWidget() : d(nullptr), dc(0), placingCommand(false)
stack = new QStackedWidget(this);
stack->addWidget(emptyView.get());
stack->addWidget(view.get());
stack->addWidget(viewWidget.get());
QHBoxLayout *layout = new QHBoxLayout(this);
layout->setSpacing(0);
@ -123,14 +129,6 @@ ProfileWidget::ProfileWidget() : d(nullptr), dc(0), placingCommand(false)
connect(ui.profPO2, &QAction::triggered, pp_gas, &qPrefPartialPressureGas::set_po2);
connect(&diveListNotifier, &DiveListNotifier::divesChanged, this, &ProfileWidget::divesChanged);
connect(&diveListNotifier, &DiveListNotifier::settingsChanged, view.get(), &ProfileWidget2::settingsChanged);
connect(&diveListNotifier, &DiveListNotifier::cylinderAdded, this, &ProfileWidget::cylindersChanged);
connect(&diveListNotifier, &DiveListNotifier::cylinderRemoved, this, &ProfileWidget::cylindersChanged);
connect(&diveListNotifier, &DiveListNotifier::cylinderEdited, this, &ProfileWidget::cylindersChanged);
connect(view.get(), &ProfileWidget2::stopAdded, this, &ProfileWidget::stopAdded);
connect(view.get(), &ProfileWidget2::stopRemoved, this, &ProfileWidget::stopRemoved);
connect(view.get(), &ProfileWidget2::stopMoved, this, &ProfileWidget::stopMoved);
connect(view.get(), &ProfileWidget2::stopEdited, this, &ProfileWidget::stopEdited);
ui.profCalcAllTissues->setChecked(qPrefTechnicalDetails::calcalltissues());
ui.profCalcCeiling->setChecked(qPrefTechnicalDetails::calcceiling());
@ -151,12 +149,38 @@ ProfileWidget::ProfileWidget() : d(nullptr), dc(0), placingCommand(false)
ui.profTissues->setChecked(qPrefTechnicalDetails::percentagegraph());
ui.profScaled->setChecked(qPrefTechnicalDetails::zoomed_plot());
ui.profInfobox->setChecked(qPrefTechnicalDetails::infobox());
//connect(&diveListNotifier, &DiveListNotifier::settingsChanged, view.get(), &ProfileWidget2::settingsChanged);
//connect(&diveListNotifier, &DiveListNotifier::cylinderAdded, this, &ProfileWidget::cylindersChanged);
//connect(&diveListNotifier, &DiveListNotifier::cylinderRemoved, this, &ProfileWidget::cylindersChanged);
//connect(&diveListNotifier, &DiveListNotifier::cylinderEdited, this, &ProfileWidget::cylindersChanged);
//connect(view.get(), &ProfileWidget2::stopAdded, this, &ProfileWidget::stopAdded);
//connect(view.get(), &ProfileWidget2::stopRemoved, this, &ProfileWidget::stopRemoved);
//connect(view.get(), &ProfileWidget2::stopMoved, this, &ProfileWidget::stopMoved);
//connect(view.get(), &ProfileWidget2::stopEdited, this, &ProfileWidget::stopEdited);
}
ProfileWidget::~ProfileWidget()
{
}
// hack around the Qt6 bug where the QML object gets destroyed and recreated
ProfileView *ProfileWidget::getView()
{
ProfileView *view = qobject_cast<ProfileView *>(viewWidget->rootObject());
if (!view)
qWarning("Oops. The root of the StatsView is not a StatsView.");
if (view) {
// try to prevent the JS garbage collection from freeing the object
// this appears to fail with Qt6 which is why we still look up the
// object from the rootObject
viewWidget->engine()->setObjectOwnership(view, QQmlEngine::CppOwnership);
view->setParent(this);
view->setVisible(isVisible()); // Synchronize visibility of widget and QtQuick-view.
}
return view;
}
void ProfileWidget::setEnabledToolbar(bool enabled)
{
for (QAction *b: toolbarActions)
@ -224,13 +248,14 @@ void ProfileWidget::plotDive(dive *dIn, int dcIn)
editDive();
}
auto view = getView();
setEnabledToolbar(d != nullptr);
if (editedDive) {
view->plotDive(editedDive.get(), dc);
setDive(editedDive.get(), dc);
} else if (d) {
view->setProfileState(d, dc);
view->resetZoom(); // when switching dive, reset the zoomLevel
//view->setProfileState(d, dc);
//view->resetZoom(); // when switching dive, reset the zoomLevel
view->plotDive(d, dc);
setDive(d, dc);
} else {
@ -273,7 +298,7 @@ void ProfileWidget::divesChanged(const QVector<dive *> &dives, DiveField field)
return;
// If we're editing the current dive and not currently
// placing command, we have to update the edited dive.
// placing a command, we have to update the edited dive.
if (editedDive) {
copy_dive(d, editedDive.get());
// TODO: Holy moly that function sends too many signals. Fix it!
@ -307,7 +332,7 @@ void ProfileWidget::cylindersChanged(struct dive *changed, int pos)
void ProfileWidget::setPlanState(const struct dive *d, int dcNr)
{
dc = dcNr;
view->setPlanState(d, dcNr);
//view->setPlanState(d, dcNr);
setDive(d, dcNr);
}
@ -329,7 +354,7 @@ void ProfileWidget::editDive()
copy_dive(d, editedDive.get()); // Work on a copy of the dive
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::EDIT);
DivePlannerPointsModel::instance()->loadFromDive(editedDive.get(), dc);
view->setEditState(editedDive.get(), dc);
//view->setEditState(editedDive.get(), dc);
}
void ProfileWidget::exitEditMode()
@ -338,7 +363,7 @@ void ProfileWidget::exitEditMode()
return;
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::NOTHING);
view->setProfileState(d, dc); // switch back to original dive before erasing the copy.
//view->setProfileState(d, dc); // switch back to original dive before erasing the copy.
editedDive.reset();
}