QmlDesigner: fix crash on exit

- use Utils::UniqueObjectPtr because it is a widget and
  can get a parent which deletes it
- delete the DesignerPropertyMap as last, so there is no
  connection to QmlEngine objects
- renamed view -> widget, where it was easy to rename it

Task-number: QDS-12480
Change-Id: I260909f2965f2943a9693b00876efcbb385d4259
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Tim Jenssen
2024-04-24 16:18:53 +02:00
parent a1829f0317
commit 10f855f3f0
5 changed files with 30 additions and 17 deletions

View File

@@ -60,10 +60,13 @@ private:
MaterialEditorView *materialEditor); MaterialEditorView *materialEditor);
PropertyName auxNamePostFix(const PropertyName &propertyName); PropertyName auxNamePostFix(const PropertyName &propertyName);
// to avoid a crash while destructing DesignerPropertyMap in the QQmlData
// this needs be destructed after m_quickWidget->engine() is destructed
DesignerPropertyMap m_backendValuesPropertyMap;
Utils::UniqueObjectPtr<QQuickWidget> m_quickWidget = nullptr; Utils::UniqueObjectPtr<QQuickWidget> m_quickWidget = nullptr;
QmlAnchorBindingProxy m_backendAnchorBinding; QmlAnchorBindingProxy m_backendAnchorBinding;
QmlModelNodeProxy m_backendModelNode; QmlModelNodeProxy m_backendModelNode;
DesignerPropertyMap m_backendValuesPropertyMap;
QScopedPointer<MaterialEditorTransaction> m_materialEditorTransaction; QScopedPointer<MaterialEditorTransaction> m_materialEditorTransaction;
QScopedPointer<MaterialEditorContextObject> m_contextObject; QScopedPointer<MaterialEditorContextObject> m_contextObject;
QPointer<MaterialEditorImageProvider> m_materialEditorImageProvider; QPointer<MaterialEditorImageProvider> m_materialEditorImageProvider;

View File

@@ -82,10 +82,10 @@ namespace QmlDesigner {
PropertyEditorQmlBackend::PropertyEditorQmlBackend(PropertyEditorView *propertyEditor, PropertyEditorQmlBackend::PropertyEditorQmlBackend(PropertyEditorView *propertyEditor,
AsynchronousImageCache &imageCache) AsynchronousImageCache &imageCache)
: m_view(new Quick2PropertyEditorView(imageCache)) : m_view(Utils::makeUniqueObjectPtr<Quick2PropertyEditorView>(imageCache))
, m_propertyEditorTransaction(new PropertyEditorTransaction(propertyEditor)) , m_propertyEditorTransaction(new PropertyEditorTransaction(propertyEditor))
, m_dummyPropertyEditorValue(new PropertyEditorValue()) , m_dummyPropertyEditorValue(new PropertyEditorValue())
, m_contextObject(new PropertyEditorContextObject(m_view)) , m_contextObject(new PropertyEditorContextObject(m_view.get()))
{ {
m_view->engine()->setOutputWarningsToStandardError(QmlDesignerPlugin::instance() m_view->engine()->setOutputWarningsToStandardError(QmlDesignerPlugin::instance()
->settings().value(DesignerSettingsKey::SHOW_PROPERTYEDITOR_WARNINGS).toBool()); ->settings().value(DesignerSettingsKey::SHOW_PROPERTYEDITOR_WARNINGS).toBool());
@@ -407,7 +407,7 @@ PropertyEditorContextObject *PropertyEditorQmlBackend::contextObject()
QQuickWidget *PropertyEditorQmlBackend::widget() QQuickWidget *PropertyEditorQmlBackend::widget()
{ {
return m_view; return m_view.get();
} }
void PropertyEditorQmlBackend::setSource(const QUrl &url) void PropertyEditorQmlBackend::setSource(const QUrl &url)

View File

@@ -10,6 +10,8 @@
#include "qmlmodelnodeproxy.h" #include "qmlmodelnodeproxy.h"
#include "quick2propertyeditorview.h" #include "quick2propertyeditorview.h"
#include <utils/uniqueobjectptr.h>
#include <nodemetainfo.h> #include <nodemetainfo.h>
#include <QQmlPropertyMap> #include <QQmlPropertyMap>
@@ -100,10 +102,13 @@ private:
static TypeName fixTypeNameForPanes(const TypeName &typeName); static TypeName fixTypeNameForPanes(const TypeName &typeName);
private: private:
Quick2PropertyEditorView *m_view; // to avoid a crash while destructing DesignerPropertyMap in the QQmlData
// this needs be destructed after m_quickWidget->engine() is destructed
DesignerPropertyMap m_backendValuesPropertyMap;
Utils::UniqueObjectPtr<Quick2PropertyEditorView> m_view = nullptr;
QmlAnchorBindingProxy m_backendAnchorBinding; QmlAnchorBindingProxy m_backendAnchorBinding;
QmlModelNodeProxy m_backendModelNode; QmlModelNodeProxy m_backendModelNode;
DesignerPropertyMap m_backendValuesPropertyMap;
QScopedPointer<PropertyEditorTransaction> m_propertyEditorTransaction; QScopedPointer<PropertyEditorTransaction> m_propertyEditorTransaction;
QScopedPointer<PropertyEditorValue> m_dummyPropertyEditorValue; QScopedPointer<PropertyEditorValue> m_dummyPropertyEditorValue;
QScopedPointer<PropertyEditorContextObject> m_contextObject; QScopedPointer<PropertyEditorContextObject> m_contextObject;

View File

@@ -43,17 +43,17 @@ static QObject *variantToQObject(const QVariant &value)
namespace QmlDesigner { namespace QmlDesigner {
TextureEditorQmlBackend::TextureEditorQmlBackend(TextureEditorView *textureEditor, AsynchronousImageCache &imageCache) TextureEditorQmlBackend::TextureEditorQmlBackend(TextureEditorView *textureEditor, AsynchronousImageCache &imageCache)
: m_view(new QQuickWidget) : m_quickWidget(new QQuickWidget)
, m_textureEditorTransaction(new TextureEditorTransaction(textureEditor)) , m_textureEditorTransaction(new TextureEditorTransaction(textureEditor))
, m_contextObject(new TextureEditorContextObject(m_view->rootContext())) , m_contextObject(new TextureEditorContextObject(m_quickWidget->rootContext()))
{ {
QImage defaultImage; QImage defaultImage;
defaultImage.load(Utils::StyleHelper::dpiSpecificImageFile(":/textureeditor/images/texture_default.png")); defaultImage.load(Utils::StyleHelper::dpiSpecificImageFile(":/textureeditor/images/texture_default.png"));
m_textureEditorImageProvider = new AssetImageProvider(imageCache, defaultImage); m_textureEditorImageProvider = new AssetImageProvider(imageCache, defaultImage);
m_view->setResizeMode(QQuickWidget::SizeRootObjectToView); m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
m_view->setObjectName(Constants::OBJECT_NAME_TEXTURE_EDITOR); m_quickWidget->setObjectName(Constants::OBJECT_NAME_TEXTURE_EDITOR);
m_view->engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); m_quickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_view->engine()->addImageProvider("qmldesigner_thumbnails", m_textureEditorImageProvider); m_quickWidget->engine()->addImageProvider("qmldesigner_thumbnails", m_textureEditorImageProvider);
m_contextObject->setBackendValues(&m_backendValuesPropertyMap); m_contextObject->setBackendValues(&m_backendValuesPropertyMap);
m_contextObject->setModel(textureEditor->model()); m_contextObject->setModel(textureEditor->model());
context()->setContextObject(m_contextObject.data()); context()->setContextObject(m_contextObject.data());
@@ -154,7 +154,7 @@ void TextureEditorQmlBackend::setValue(const QmlObjectNode &, const PropertyName
QQmlContext *TextureEditorQmlBackend::context() const QQmlContext *TextureEditorQmlBackend::context() const
{ {
return m_view->rootContext(); return m_quickWidget->rootContext();
} }
TextureEditorContextObject *TextureEditorQmlBackend::contextObject() const TextureEditorContextObject *TextureEditorQmlBackend::contextObject() const
@@ -164,12 +164,12 @@ TextureEditorContextObject *TextureEditorQmlBackend::contextObject() const
QQuickWidget *TextureEditorQmlBackend::widget() const QQuickWidget *TextureEditorQmlBackend::widget() const
{ {
return m_view; return m_quickWidget.get();
} }
void TextureEditorQmlBackend::setSource(const QUrl &url) void TextureEditorQmlBackend::setSource(const QUrl &url)
{ {
m_view->setSource(url); m_quickWidget->setSource(url);
} }
QmlAnchorBindingProxy &TextureEditorQmlBackend::backendAnchorBinding() QmlAnchorBindingProxy &TextureEditorQmlBackend::backendAnchorBinding()

View File

@@ -7,6 +7,8 @@
#include "qmlanchorbindingproxy.h" #include "qmlanchorbindingproxy.h"
#include "qmlmodelnodeproxy.h" #include "qmlmodelnodeproxy.h"
#include <utils/uniqueobjectptr.h>
#include <nodemetainfo.h> #include <nodemetainfo.h>
class PropertyEditorValue; class PropertyEditorValue;
@@ -58,10 +60,13 @@ private:
TextureEditorView *textureEditor); TextureEditorView *textureEditor);
PropertyName auxNamePostFix(const PropertyName &propertyName); PropertyName auxNamePostFix(const PropertyName &propertyName);
QQuickWidget *m_view = nullptr; // to avoid a crash while destructing DesignerPropertyMap in the QQmlData
// this needs be destructed after m_quickWidget->engine() is destructed
DesignerPropertyMap m_backendValuesPropertyMap;
Utils::UniqueObjectPtr<QQuickWidget> m_quickWidget = nullptr;
QmlAnchorBindingProxy m_backendAnchorBinding; QmlAnchorBindingProxy m_backendAnchorBinding;
QmlModelNodeProxy m_backendModelNode; QmlModelNodeProxy m_backendModelNode;
DesignerPropertyMap m_backendValuesPropertyMap;
QScopedPointer<TextureEditorTransaction> m_textureEditorTransaction; QScopedPointer<TextureEditorTransaction> m_textureEditorTransaction;
QScopedPointer<TextureEditorContextObject> m_contextObject; QScopedPointer<TextureEditorContextObject> m_contextObject;
AssetImageProvider *m_textureEditorImageProvider = nullptr; AssetImageProvider *m_textureEditorImageProvider = nullptr;