Compare commits

...

3 Commits

Author SHA1 Message Date
Berthold Stoeger
2f044039dd desktop: update comment to reflect reason for QQuickItem destruction
Explain the ominous behavior that leads to the StatsView being
destroyed under our feet by Qt6.

Also, don't generate the view in the destructor. No point in
doing that, when we have to regenerate it anyway for each
access.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2023-04-30 17:24:06 +02:00
Berthold Stoeger
515f76e9a9 cleanup: move index variable into loop scope
Less clutter.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2023-04-30 17:24:05 +02:00
Berthold Stoeger
f831027d65 desktop: set Qt::AA_ShareOpenGLContexts application flag
Qt6 destroys QQuickItems when reparenting their parent widget.
This can be prevented for OpenGL-backends by setting this
application-wide flag on startup. Sadly, it doesn't help
for non-OpenGL based applications.

Make the sharing optional (by commandline flag --no-opengl-sharing)
to test the destruction/recreation of QQuickItems case.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2023-04-30 17:22:41 +02:00
3 changed files with 31 additions and 7 deletions

View File

@ -91,6 +91,7 @@ static void print_help()
printf("\n --dc-product=product Set the dive computer to download from");
printf("\n --device=device Set the device to download from");
#endif
printf("\n --no-opengl-sharing Don't share OpenGL contexts between QQuickItems (for testing)");
printf("\n --cloud-timeout=<nr> Set timeout for cloud connection (0 < timeout < 60)\n\n");
}
@ -149,6 +150,10 @@ void parse_argument(const char *arg)
++force_root;
return;
}
if (strcmp(arg, "--no-opengl-sharing") == 0) {
// This was already checked in main()
return;
}
#if SUBSURFACE_DOWNLOADER
if (strncmp(arg, "--dc-vendor=", sizeof("--dc-vendor=") - 1) == 0) {
prefs.dive_computer.vendor = strdup(arg + sizeof("--dc-vendor=") - 1);

View File

@ -91,19 +91,24 @@ StatsWidget::StatsWidget(QWidget *parent) : QWidget(parent)
ui.stats->setSource(urlStatsView);
ui.stats->setResizeMode(QQuickWidget::SizeRootObjectToView);
(void)getView();
}
// hack around the Qt6 bug where the QML object gets destroyed and recreated
// The Qt-developers do not have their ownership management under control.
// This is not surprising to anyone who has looked at their source code.
// In contradiction to the documentation, starting with Qt6, QQuickItems
// _will_ be deleted when the parent widgets are reparented, even when
// CppOwnership is set. This can be prevented for OpenGL backends, but not
// for others. Therefore, we have to _always_ refetch the view from the QML page.
// For details and precise conditions, see comments and code in
// QQuickWidgetPrivate::handleWindowChange().
// Ultimately, we will have to change the way widgets are hidden/shown in
// the MainWindow.
StatsView *StatsWidget::getView()
{
StatsView *view = qobject_cast<StatsView *>(ui.stats->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 ui.stats rootObject
ui.stats->engine()->setObjectOwnership(view, QQmlEngine::CppOwnership);
view->setParent(this);
view->setVisible(isVisible()); // Synchronize visibility of widget and QtQuick-view.

View File

@ -13,6 +13,7 @@
#include "core/qt-gui.h"
#include "core/qthelper.h"
#include "core/subsurfacestartup.h"
#include "core/subsurface-string.h"
#include "core/settings/qPref.h"
#include "core/tag.h"
#include "desktop-widgets/mainwindow.h"
@ -38,9 +39,22 @@ int main(int argc, char **argv)
if (verbose) /* print the version if the Win32 console_init() code enabled verbose. */
print_version();
int i;
bool no_filenames = true;
QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
// Allow OpenGL-based QtQuick backends to share OpenGL contexts.
// This avoids destruction of QQuickItems if their parent widgets are moved between widgets in Qt6.
// Sadly, this does not help when running on non-OpenGL backends.
// Allow for turning this off to test destruction of QQuickItems.
// The parameter is checked here because QCoreApplication::parameters() only
// works after instantiation of the QApplication class, but the flag has
// to be set bofore.
if (std::any_of(argv + 1, argv + argc,
[](char *arg) { return same_string(arg, "--no-opengl-sharing"); })) {
fprintf(stderr, "Disabling sharing of OpenGL contexts\n");
} else {
QGuiApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
}
std::unique_ptr<QApplication> app(new QApplication(argc, argv));
QStringList files;
QStringList importedFiles;
@ -50,7 +64,7 @@ int main(int argc, char **argv)
const char *default_filename = system_default_filename();
subsurface_mkdir(default_directory);
for (i = 1; i < arguments.length(); i++) {
for (int i = 1; i < arguments.length(); i++) {
QString a = arguments.at(i);
if (a.isEmpty())
continue;