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

@ -22,7 +22,6 @@
#include "desktop-widgets/divelogexportdialog.h"
#include "desktop-widgets/diveshareexportdialog.h"
#include "desktop-widgets/subsurfacewebservices.h"
#include "profile-widget/profilewidget2.h"
// Retrieves the current unit settings defined in the Subsurface preferences.
#define GET_UNIT(name, field, f, t) \

View file

@ -57,7 +57,6 @@
#include "commands/command.h"
#include "profilewidget.h"
#include "profile-widget/profilewidget2.h"
#ifndef NO_PRINTING
#include "desktop-widgets/printdialog.h"

View file

@ -8,7 +8,6 @@
#include "qt-models/cylindermodel.h"
#include "qt-models/models.h"
#include "desktop-widgets/starwidget.h"
#include "profile-widget/profilewidget2.h"
#include "qt-models/tankinfomodel.h"
#include "qt-models/weightsysteminfomodel.h"
#include "qt-models/weightmodel.h"

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();
}

View file

@ -10,8 +10,9 @@
#include <vector>
struct dive;
class ProfileWidget2;
class ProfileView;
class EmptyView;
class QQuickWidget;
class QStackedWidget;
class ProfileWidget : public QWidget {
@ -19,7 +20,6 @@ class ProfileWidget : public QWidget {
public:
ProfileWidget();
~ProfileWidget();
std::unique_ptr<ProfileWidget2> view;
void plotDive(struct dive *d, int dc); // Attempt to keep DC number id dc < 0
void plotCurrentDive();
void setPlanState(const struct dive *d, int dc);
@ -40,6 +40,8 @@ slots:
void stopMoved(int count);
void stopEdited();
private:
ProfileView *getView();
std::unique_ptr<QQuickWidget> viewWidget;
std::unique_ptr<EmptyView> emptyView;
std::vector<QAction *> toolbarActions;
Ui::ProfileWidget ui;

View file

@ -0,0 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
import org.subsurfacedivelog.mobile 1.0
ProfileView {
property real dpr: 1.0
}

View file

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/qml">
<file>profileview.qml</file>
</qresource>
</RCC>

View file

@ -19,7 +19,6 @@
#include "libdivecomputer/parser.h"
#include "desktop-widgets/divelistview.h"
#include "core/selection.h"
#include "profile-widget/profilewidget2.h"
#include "commands/command.h"
#include "core/metadata.h"
#include "core/range.h"

View file

@ -2,7 +2,6 @@
#include "TabDiveInformation.h"
#include "maintab.h"
#include "ui_TabDiveInformation.h"
#include "profile-widget/profilewidget2.h"
#include "../tagwidget.h"
#include "commands/command.h"
#include "core/subsurface-string.h"