aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml23
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp20
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h10
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp2
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp2
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp140
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h26
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp199
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h39
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp2
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp4
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5testnodeinstanceserver.cpp4
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp29
13 files changed, 293 insertions, 207 deletions
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
index 002ed7bc04..1bdc73fb22 100644
--- a/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
+++ b/share/qtcreator/qml/qmlpuppet/mockfiles/EditView3D.qml
@@ -57,6 +57,8 @@ Item {
property var selectionBoxes: []
property rect viewPortRect: Qt.rect(0, 0, 1000, 1000)
+ property bool shuttingDown: false
+
signal selectionChanged(var selectedNodes)
signal commitObjectProperty(var object, var propName)
signal changeObjectProperty(var object, var propName)
@@ -71,6 +73,11 @@ Item {
onActiveSceneChanged: updateActiveScene()
+ function aboutToShutDown()
+ {
+ shuttingDown = true;
+ }
+
function createEditView()
{
var component = Qt.createComponent("SceneView3D.qml");
@@ -125,8 +132,12 @@ Item {
} else {
// When active scene is deleted, this function gets called by object deletion
// handlers without going through setActiveScene, so make sure sceneId is cleared.
- sceneId = "";
- storeCurrentToolStates();
+ // This is skipped during application shutdown, as calling QQuickText::setText()
+ // during application shutdown can crash the application.
+ if (!shuttingDown) {
+ sceneId = "";
+ storeCurrentToolStates();
+ }
}
notifyActiveSceneChange();
@@ -704,6 +715,10 @@ Item {
Text {
id: gizmoLabelText
text: {
+ // This is skipped during application shutdown, as calling QQuickText::setText()
+ // during application shutdown can crash the application.
+ if (shuttingDown)
+ return text;
var l = Qt.locale();
var targetProperty;
if (viewRoot.selectedNode) {
@@ -738,6 +753,10 @@ Item {
Text {
id: rotateGizmoLabelText
text: {
+ // This is skipped during application shutdown, as calling QQuickText::setText()
+ // during application shutdown can crash the application.
+ if (shuttingDown)
+ return text;
var l = Qt.locale();
if (rotateGizmo.targetNode) {
var degrees = rotateGizmo.currentAngle * (180 / Math.PI);
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
index 552d323247..64d790c6a7 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp
@@ -189,9 +189,14 @@ NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstance
Internal::QmlPrivateGate::registerFixResourcePathsForObjectCallBack();
}
+NodeInstanceServer::~NodeInstanceServer()
+{
+ m_objectInstanceHash.clear();
+}
+
QList<ServerNodeInstance> NodeInstanceServer::createInstances(const QVector<InstanceContainer> &containerVector)
{
- Q_ASSERT(declarativeView() || quickView());
+ Q_ASSERT(declarativeView() || quickWindow());
QList<ServerNodeInstance> instanceList;
for (const InstanceContainer &instanceContainer : containerVector) {
ServerNodeInstance instance;
@@ -207,7 +212,6 @@ QList<ServerNodeInstance> NodeInstanceServer::createInstances(const QVector<Inst
m_rootNodeInstance = instance;
if (quickView())
quickView()->setContent(fileUrl(), m_importComponent, m_rootNodeInstance.rootQuickItem());
- resizeCanvasSizeToRootItemSize();
}
foreach (QQmlContext* context, allSubContextsForObject(instance.internalObject()))
@@ -442,7 +446,7 @@ void NodeInstanceServer::removeSharedMemory(const RemoveSharedMemoryCommand &/*c
void NodeInstanceServer::setupImports(const QVector<AddImportContainer> &containerVector)
{
- Q_ASSERT(quickView());
+ Q_ASSERT(quickWindow());
QSet<QString> importStatementSet;
QString qtQuickImport;
@@ -497,8 +501,9 @@ void NodeInstanceServer::setupOnlyWorkingImports(const QStringList &workingImpor
QByteArray componentCode = workingImportStatementList.join("\n").toUtf8().append("\n");
m_importCode = componentCode;
- m_importComponent = new QQmlComponent(engine(), quickView());
- quickView()->setContent(fileUrl(), m_importComponent, quickView()->rootObject());
+ m_importComponent = new QQmlComponent(engine(), quickWindow());
+ if (quickView())
+ quickView()->setContent(fileUrl(), m_importComponent, quickView()->rootObject());
m_importComponent->setData(componentCode.append("\nItem {}\n"), fileUrl());
m_importComponentObject = m_importComponent->create();
@@ -942,11 +947,9 @@ void NodeInstanceServer::setInstancePropertyVariant(const PropertyValueContainer
if (hasInstanceForId(valueContainer.instanceId())) {
ServerNodeInstance instance = instanceForId(valueContainer.instanceId());
-
const PropertyName name = valueContainer.name();
const QVariant value = valueContainer.value();
-
if (activeStateInstance().isValid() && !instance.isSubclassOf("QtQuick/PropertyChanges")) {
bool stateValueWasUpdated = activeStateInstance().updateStateVariant(instance, name, value);
if (!stateValueWasUpdated) {
@@ -962,6 +965,9 @@ void NodeInstanceServer::setInstancePropertyVariant(const PropertyValueContainer
if (valueContainer.isDynamic() && valueContainer.instanceId() == 0 && engine())
rootContext()->setContextProperty(QString::fromUtf8(name), Internal::QmlPrivateGate::fixResourcePaths(value));
+
+ if (valueContainer.instanceId() == 0 && (name == "width" || name == "height" || name == "x" || name == "y"))
+ resizeCanvasToRootItem();
}
}
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h
index 021a2bd6d0..f44a0047fe 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.h
@@ -31,6 +31,7 @@
#include <QSet>
#include <QStringList>
#include <QPointer>
+#include <QImage>
#ifdef MULTILANGUAGE_TRANSLATIONPROVIDER
#include <multilanguagelink.h>
@@ -90,6 +91,7 @@ QT_BEGIN_NAMESPACE
class QFileSystemWatcher;
class QQmlView;
class QQuickView;
+class QQuickWindow;
class QQmlEngine;
class QFileInfo;
class QQmlComponent;
@@ -131,6 +133,7 @@ public:
};
explicit NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient);
+ ~NodeInstanceServer() override;
void createInstances(const CreateInstancesCommand &command) override;
void changeFileUrl(const ChangeFileUrlCommand &command) override;
@@ -192,6 +195,9 @@ public:
virtual QQmlView *declarativeView() const = 0;
virtual QQuickView *quickView() const = 0;
+ virtual QQuickWindow *quickWindow() const = 0;
+ virtual QQuickItem *rootItem() const = 0;
+ virtual void setRootItem(QQuickItem *item) = 0;
void sendDebugOutput(DebugOutputCommand::Type type, const QString &message, qint32 instanceId = 0);
void sendDebugOutput(DebugOutputCommand::Type type,
@@ -211,6 +217,8 @@ public:
virtual void handleInstanceLocked(const ServerNodeInstance &instance, bool enable, bool checkAncestors);
virtual void handleInstanceHidden(const ServerNodeInstance &instance, bool enable, bool checkAncestors);
+ virtual QImage grabWindow() = 0;
+
public slots:
void refreshLocalFileProperty(const QString &path);
void refreshDummyData(const QString &path);
@@ -288,7 +296,7 @@ protected:
QList<QQmlContext*> allSubContextsForObject(QObject *object);
static QList<QObject*> allSubObjectsForObject(QObject *object);
- virtual void resizeCanvasSizeToRootItemSize() = 0;
+ virtual void resizeCanvasToRootItem() = 0;
void setupState(qint32 stateInstanceId);
private:
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp
index d24c4e5552..4581bc6ce8 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5captureimagenodeinstanceserver.cpp
@@ -70,7 +70,7 @@ void Qt5CaptureImageNodeInstanceServer::collectItemChangesAndSendChangeCommands(
auto rooNodeInstance = rootNodeInstance();
rooNodeInstance.rootQuickItem()->setClip(true);
- DesignerSupport::polishItems(quickView());
+ DesignerSupport::polishItems(quickWindow());
QImage image = renderImage(rooNodeInstance);
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp
index 7fb87defb0..b9ba3860a3 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5capturepreviewnodeinstanceserver.cpp
@@ -88,7 +88,7 @@ void Qt5CapturePreviewNodeInstanceServer::collectItemChangesAndSendChangeCommand
if (!inFunction) {
inFunction = true;
- DesignerSupport::polishItems(quickView());
+ DesignerSupport::polishItems(quickWindow());
QVector<CapturedDataCommand::StateData> stateDatas;
stateDatas.push_back(collectStateData(rootNodeInstance(), nodeInstances(), 0));
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
index 8421064021..521ef40765 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp
@@ -88,11 +88,7 @@
#include <QtGui/qguiapplication.h>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
-#include <QtGui/private/qrhi_p.h>
-#include <QtQuick/private/qquickwindow_p.h>
-#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qquickrendercontrol_p.h>
-#include <QtQuick/private/qquickrendertarget_p.h>
#endif
#ifdef QUICK3D_MODULE
@@ -149,7 +145,7 @@ void Qt5InformationNodeInstanceServer::createAuxiliaryQuickView(const QUrl &url,
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
viewData.window = new QQuickView(quickView()->engine(), quickView());
viewData.window->setFormat(quickView()->format());
- DesignerSupport::createOpenGLContext(static_cast<QQuickView *>(viewData.window));
+ DesignerSupport::createOpenGLContext(static_cast<QQuickView *>(viewData.window.data()));
#else
viewData.renderControl = new QQuickRenderControl;
viewData.window = new QQuickWindow(viewData.renderControl);
@@ -165,7 +161,7 @@ void Qt5InformationNodeInstanceServer::createAuxiliaryQuickView(const QUrl &url,
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- DesignerSupport::setRootItem(static_cast<QQuickView *>(viewData.window), viewData.rootItem);
+ DesignerSupport::setRootItem(static_cast<QQuickView *>(viewData.window.data()), viewData.rootItem);
#else
viewData.window->contentItem()->setSize(viewData.rootItem->size());
viewData.window->setGeometry(0, 0, viewData.rootItem->width(), viewData.rootItem->height());
@@ -249,120 +245,6 @@ void Qt5InformationNodeInstanceServer::handleInputEvents()
}
}
-bool Qt5InformationNodeInstanceServer::initRhi(RenderViewData &viewData)
-{
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- if (!viewData.renderControl) {
- qWarning() << __FUNCTION__ << "Render control not created";
- return false;
- }
-
- if (!viewData.rhi) {
- QQuickRenderControlPrivate *rd = QQuickRenderControlPrivate::get(viewData.renderControl);
- viewData.rhi = rd->rhi;
-
- if (!viewData.rhi) {
- qWarning() << __FUNCTION__ << "Rhi is null";
- return false;
- }
- }
-
- auto cleanRhiResources = [&viewData]() {
- // Releasing cached resources is a workaround for bug QTBUG-88761
- auto renderer = QQuickWindowPrivate::get(viewData.window)->renderer;
- if (renderer)
- renderer->releaseCachedResources();
-
- if (viewData.rpDesc) {
- viewData.rpDesc->deleteLater();
- viewData.rpDesc = nullptr;
- }
- if (viewData.texTarget) {
- viewData.texTarget->deleteLater();
- viewData.texTarget = nullptr;
- }
- if (viewData.buffer) {
- viewData.buffer->deleteLater();
- viewData.buffer = nullptr;
- }
- if (viewData.texture) {
- viewData.texture->deleteLater();
- viewData.texture = nullptr;
- }
- };
- if (viewData.bufferDirty) {
- cleanRhiResources();
- viewData.bufferDirty = false;
- }
-
- const QSize size = viewData.rootItem->size().toSize();
- viewData.texture = viewData.rhi->newTexture(QRhiTexture::RGBA8, size, 1,
- QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource);
- if (!viewData.texture->create()) {
- qWarning() << __FUNCTION__ << "QRhiTexture creation failed";
- cleanRhiResources();
- return false;
- }
-
- viewData.buffer = viewData.rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, size, 1);
- if (!viewData.buffer->create()) {
- qWarning() << __FUNCTION__ << "Depth/stencil buffer creation failed";
- cleanRhiResources();
- return false;
- }
-
- QRhiTextureRenderTargetDescription rtDesc(QRhiColorAttachment(viewData.texture));
- rtDesc.setDepthStencilBuffer(viewData.buffer);
- viewData.texTarget = viewData.rhi->newTextureRenderTarget(rtDesc);
- viewData.rpDesc = viewData.texTarget->newCompatibleRenderPassDescriptor();
- viewData.texTarget->setRenderPassDescriptor(viewData.rpDesc);
- if (!viewData.texTarget->create()) {
- qWarning() << __FUNCTION__ << "Texture render target creation failed";
- cleanRhiResources();
- return false;
- }
-
- // redirect Qt Quick rendering into our texture
- viewData.window->setRenderTarget(QQuickRenderTarget::fromRhiRenderTarget(viewData.texTarget));
-#endif
- return true;
-}
-
-QImage Qt5InformationNodeInstanceServer::grabRenderControl(RenderViewData &viewData)
-{
- QImage renderImage;
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- if (viewData.bufferDirty && !initRhi(viewData))
- return renderImage;
-
- viewData.renderControl->polishItems();
- viewData.renderControl->beginFrame();
- viewData.renderControl->sync();
- viewData.renderControl->render();
-
- bool readCompleted = false;
- QRhiReadbackResult readResult;
- readResult.completed = [&] {
- readCompleted = true;
- QImage wrapperImage(reinterpret_cast<const uchar *>(readResult.data.constData()),
- readResult.pixelSize.width(), readResult.pixelSize.height(),
- QImage::Format_RGBA8888_Premultiplied);
- if (viewData.rhi->isYUpInFramebuffer())
- renderImage = wrapperImage.mirrored();
- else
- renderImage = wrapperImage.copy();
- };
- QRhiResourceUpdateBatch *readbackBatch = viewData.rhi->nextResourceUpdateBatch();
- readbackBatch->readBackTexture(viewData.texture, &readResult);
-
- QQuickRenderControlPrivate *rd = QQuickRenderControlPrivate::get(viewData.renderControl);
- rd->cb->resourceUpdate(readbackBatch);
-
- viewData.renderControl->endFrame();
-#endif
- return renderImage;
-}
-
void Qt5InformationNodeInstanceServer::createEditView3D()
{
#ifdef QUICK3D_MODULE
@@ -1000,17 +882,13 @@ Qt5InformationNodeInstanceServer::~Qt5InformationNodeInstanceServer()
m_render3DEditViewTimer.stop();
m_inputEventTimer.stop();
- delete m_editView3DData.rootItem;
- delete m_editView3DData.window;
- delete m_modelNode3DImageViewData.rootItem;
- delete m_modelNode3DImageViewData.window;
- delete m_modelNode2DImageViewData.rootItem;
- delete m_modelNode2DImageViewData.window;
-
for (auto view : qAsConst(m_view3Ds))
view->disconnect();
- for (auto scene : qAsConst(m_3DSceneMap))
- scene->disconnect();
+ for (auto node : qAsConst(m_3DSceneMap))
+ node->disconnect();
+
+ if (m_editView3DData.rootItem)
+ QMetaObject::invokeMethod(m_editView3DData.rootItem, "aboutToShutDown", Qt::DirectConnection);
}
void Qt5InformationNodeInstanceServer::sendTokenBack()
@@ -1424,12 +1302,12 @@ void Qt5InformationNodeInstanceServer::collectItemChangesAndSendChangeCommands()
if (!inFunction) {
inFunction = true;
- DesignerSupport::polishItems(quickView());
+ DesignerSupport::polishItems(quickWindow());
QSet<ServerNodeInstance> informationChangedInstanceSet;
QVector<InstancePropertyPair> propertyChangedList;
- if (quickView()) {
+ if (quickWindow()) {
foreach (QQuickItem *item, allItems()) {
if (item && hasInstanceForObject(item)) {
ServerNodeInstance instance = instanceForObject(item);
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
index 47dacd45db..353f57b3fc 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.h
@@ -39,15 +39,6 @@
QT_BEGIN_NAMESPACE
class QDragMoveEvent;
-class QQuickWindow;
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
-class QQuickRenderControl;
-class QRhi;
-class QRhiTexture;
-class QRhiRenderBuffer;
-class QRhiTextureRenderTarget;
-class QRhiRenderPassDescriptor;
-#endif
QT_END_NAMESPACE
namespace QmlDesigner {
@@ -141,23 +132,6 @@ private:
void updateLockedAndHiddenStates(const QSet<ServerNodeInstance> &instances);
void handleInputEvents();
- struct RenderViewData {
- QQuickWindow *window = nullptr;
- QQuickItem *rootItem = nullptr;
- QQuickItem *contentItem = nullptr;
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- bool bufferDirty = true;
- QQuickRenderControl *renderControl = nullptr;
- QRhi *rhi = nullptr;
- QRhiTexture *texture = nullptr;
- QRhiRenderBuffer *buffer = nullptr;
- QRhiTextureRenderTarget *texTarget = nullptr;
- QRhiRenderPassDescriptor *rpDesc = nullptr;
-#endif
- };
-
- bool initRhi(RenderViewData &viewData);
- QImage grabRenderControl(RenderViewData &viewData);
void createAuxiliaryQuickView(const QUrl &url, RenderViewData &viewData);
RenderViewData m_editView3DData;
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
index 90f959dd2b..620ed0352b 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp
@@ -31,6 +31,7 @@
#include <QQuickItem>
#include <QQuickView>
+#include <QQuickWindow>
#include <designersupportdelegate.h>
#include <addimportcontainer.h>
@@ -40,6 +41,14 @@
#include <QDebug>
#include <QOpenGLContext>
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+#include <QtGui/private/qrhi_p.h>
+#include <QtQuick/private/qquickwindow_p.h>
+#include <QtQuick/private/qsgrenderer_p.h>
+#include <QtQuick/private/qquickrendercontrol_p.h>
+#include <QtQuick/private/qquickrendertarget_p.h>
+#endif
+
namespace QmlDesigner {
Qt5NodeInstanceServer::Qt5NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient)
@@ -50,30 +59,44 @@ Qt5NodeInstanceServer::Qt5NodeInstanceServer(NodeInstanceClientInterface *nodeIn
Qt5NodeInstanceServer::~Qt5NodeInstanceServer()
{
- delete quickView();
+ delete quickWindow();
}
QQuickView *Qt5NodeInstanceServer::quickView() const
{
- return m_quickView.data();
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ return static_cast<QQuickView *>(m_viewData.window.data());
+#else
+ return nullptr;
+#endif
}
-void Qt5NodeInstanceServer::initializeView()
+QQuickWindow *Qt5NodeInstanceServer::quickWindow() const
{
- Q_ASSERT(!quickView());
+ return m_viewData.window.data();
+}
- m_quickView = new QQuickView;
+void Qt5NodeInstanceServer::initializeView()
+{
+ Q_ASSERT(!quickWindow());
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ auto view = new QQuickView;
+ m_viewData.window = view;
/* enables grab window without show */
- QSurfaceFormat surfaceFormat = m_quickView->requestedFormat();
+ QSurfaceFormat surfaceFormat = view->requestedFormat();
surfaceFormat.setVersion(4, 1);
surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(surfaceFormat);
-
- m_quickView->setFormat(surfaceFormat);
-
- DesignerSupport::createOpenGLContext(m_quickView.data());
+ view->setFormat(surfaceFormat);
+
+ DesignerSupport::createOpenGLContext(view);
+ m_qmlEngine = view->engine();
+#else
+ m_viewData.renderControl = new QQuickRenderControl;
+ m_viewData.window = new QQuickWindow(m_viewData.renderControl);
+ m_viewData.renderControl->initialize();
+ m_qmlEngine = new QQmlEngine;
#endif
if (qEnvironmentVariableIsSet("QML_FILE_SELECTORS")) {
@@ -90,16 +113,39 @@ QQmlView *Qt5NodeInstanceServer::declarativeView() const
return nullptr;
}
-QQmlEngine *Qt5NodeInstanceServer::engine() const
+QQuickItem *Qt5NodeInstanceServer::rootItem() const
{
- if (quickView())
- return quickView()->engine();
+ return m_viewData.rootItem;
+}
- return nullptr;
+void Qt5NodeInstanceServer::setRootItem(QQuickItem *item)
+{
+ m_viewData.rootItem = item;
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ DesignerSupport::setRootItem(quickView(), item);
+#else
+ quickWindow()->setGeometry(0, 0, item->width(), item->height());
+ // Insert an extra item above the root to adjust root item position to 0,0 to make entire
+ // item to be always rendered.
+ if (!m_viewData.contentItem)
+ m_viewData.contentItem = new QQuickItem(quickWindow()->contentItem());
+ m_viewData.contentItem->setPosition(-item->position());
+ item->setParentItem(m_viewData.contentItem);
+#endif
}
-void Qt5NodeInstanceServer::resizeCanvasSizeToRootItemSize()
+QQmlEngine *Qt5NodeInstanceServer::engine() const
{
+ return m_qmlEngine;
+}
+
+void Qt5NodeInstanceServer::resizeCanvasToRootItem()
+{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ m_viewData.bufferDirty = true;
+ m_viewData.contentItem->setPosition(-m_viewData.rootItem->position());
+#endif
+ quickWindow()->resize(rootNodeInstance().boundingRect().size().toSize());
}
void Qt5NodeInstanceServer::resetAllItems()
@@ -116,7 +162,7 @@ void Qt5NodeInstanceServer::setupScene(const CreateSceneCommand &command)
setupDummyData(command.fileUrl);
setupInstances(command);
- quickView()->resize(rootNodeInstance().boundingRect().size().toSize());
+ resizeCanvasToRootItem();
}
QList<QQuickItem*> subItems(QQuickItem *parentItem)
@@ -138,6 +184,127 @@ QList<QQuickItem*> Qt5NodeInstanceServer::allItems() const
return QList<QQuickItem*>();
}
+bool Qt5NodeInstanceServer::initRhi(RenderViewData &viewData)
+{
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ if (!viewData.renderControl) {
+ qWarning() << __FUNCTION__ << "Render control not created";
+ return false;
+ }
+
+ if (!viewData.rhi) {
+ QQuickRenderControlPrivate *rd = QQuickRenderControlPrivate::get(viewData.renderControl);
+ viewData.rhi = rd->rhi;
+
+ if (!viewData.rhi) {
+ qWarning() << __FUNCTION__ << "Rhi is null";
+ return false;
+ }
+ }
+
+ auto cleanRhiResources = [&viewData]() {
+ // Releasing cached resources is a workaround for bug QTBUG-88761
+ auto renderer = QQuickWindowPrivate::get(viewData.window)->renderer;
+ if (renderer)
+ renderer->releaseCachedResources();
+
+ if (viewData.rpDesc) {
+ viewData.rpDesc->deleteLater();
+ viewData.rpDesc = nullptr;
+ }
+ if (viewData.texTarget) {
+ viewData.texTarget->deleteLater();
+ viewData.texTarget = nullptr;
+ }
+ if (viewData.buffer) {
+ viewData.buffer->deleteLater();
+ viewData.buffer = nullptr;
+ }
+ if (viewData.texture) {
+ viewData.texture->deleteLater();
+ viewData.texture = nullptr;
+ }
+ };
+ if (viewData.bufferDirty) {
+ cleanRhiResources();
+ viewData.bufferDirty = false;
+ }
+
+ const QSize size = viewData.window->size();
+ viewData.texture = viewData.rhi->newTexture(QRhiTexture::RGBA8, size, 1,
+ QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource);
+ if (!viewData.texture->create()) {
+ qWarning() << __FUNCTION__ << "QRhiTexture creation failed";
+ cleanRhiResources();
+ return false;
+ }
+
+ viewData.buffer = viewData.rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, size, 1);
+ if (!viewData.buffer->create()) {
+ qWarning() << __FUNCTION__ << "Depth/stencil buffer creation failed";
+ cleanRhiResources();
+ return false;
+ }
+
+ QRhiTextureRenderTargetDescription rtDesc(QRhiColorAttachment(viewData.texture));
+ rtDesc.setDepthStencilBuffer(viewData.buffer);
+ viewData.texTarget = viewData.rhi->newTextureRenderTarget(rtDesc);
+ viewData.rpDesc = viewData.texTarget->newCompatibleRenderPassDescriptor();
+ viewData.texTarget->setRenderPassDescriptor(viewData.rpDesc);
+ if (!viewData.texTarget->create()) {
+ qWarning() << __FUNCTION__ << "Texture render target creation failed";
+ cleanRhiResources();
+ return false;
+ }
+
+ // redirect Qt Quick rendering into our texture
+ viewData.window->setRenderTarget(QQuickRenderTarget::fromRhiRenderTarget(viewData.texTarget));
+#endif
+ return true;
+}
+
+QImage Qt5NodeInstanceServer::grabRenderControl(RenderViewData &viewData)
+{
+ QImage renderImage;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ if (viewData.bufferDirty && !initRhi(viewData))
+ return renderImage;
+
+ viewData.renderControl->polishItems();
+ viewData.renderControl->beginFrame();
+ viewData.renderControl->sync();
+ viewData.renderControl->render();
+
+ bool readCompleted = false;
+ QRhiReadbackResult readResult;
+ readResult.completed = [&] {
+ readCompleted = true;
+ QImage wrapperImage(reinterpret_cast<const uchar *>(readResult.data.constData()),
+ readResult.pixelSize.width(), readResult.pixelSize.height(),
+ QImage::Format_RGBA8888_Premultiplied);
+ if (viewData.rhi->isYUpInFramebuffer())
+ renderImage = wrapperImage.mirrored();
+ else
+ renderImage = wrapperImage.copy();
+ };
+ QRhiResourceUpdateBatch *readbackBatch = viewData.rhi->nextResourceUpdateBatch();
+ readbackBatch->readBackTexture(viewData.texture, &readResult);
+
+ QQuickRenderControlPrivate *rd = QQuickRenderControlPrivate::get(viewData.renderControl);
+ rd->cb->resourceUpdate(readbackBatch);
+
+ viewData.renderControl->endFrame();
+#endif
+ return renderImage;
+}
+
+QImage Qt5NodeInstanceServer::grabWindow()
+{
+ if (m_viewData.rootItem)
+ return grabRenderControl(m_viewData);
+ return {};
+}
+
void Qt5NodeInstanceServer::refreshBindings()
{
DesignerSupport::refreshExpressions(context());
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h
index ca43363a9a..e6a2754f99 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.h
@@ -26,12 +26,22 @@
#pragma once
#include <QtGlobal>
+#include <QtQuick/qquickwindow.h>
#include "nodeinstanceserver.h"
#include <designersupportdelegate.h>
QT_BEGIN_NAMESPACE
class QQuickItem;
+class QQmlEngine;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+class QQuickRenderControl;
+class QRhi;
+class QRhiTexture;
+class QRhiRenderBuffer;
+class QRhiTextureRenderTarget;
+class QRhiRenderPassDescriptor;
+#endif
QT_END_NAMESPACE
namespace QmlDesigner {
@@ -44,7 +54,11 @@ public:
~Qt5NodeInstanceServer() override;
QQuickView *quickView() const override;
+ QQuickWindow *quickWindow() const override;
QQmlView *declarativeView() const override;
+ QQuickItem *rootItem() const override;
+ void setRootItem(QQuickItem *item) override;
+
QQmlEngine *engine() const override;
void refreshBindings() override;
@@ -54,16 +68,37 @@ public:
void clearScene(const ClearSceneCommand &command) override;
void reparentInstances(const ReparentInstancesCommand &command) override;
+ QImage grabWindow() override;
+
protected:
void initializeView() override;
- void resizeCanvasSizeToRootItemSize() override;
+ void resizeCanvasToRootItem() override;
void resetAllItems();
void setupScene(const CreateSceneCommand &command) override;
QList<QQuickItem*> allItems() const;
+ struct RenderViewData {
+ QPointer<QQuickWindow> window = nullptr;
+ QQuickItem *rootItem = nullptr;
+ QQuickItem *contentItem = nullptr;
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool bufferDirty = true;
+ QQuickRenderControl *renderControl = nullptr;
+ QRhi *rhi = nullptr;
+ QRhiTexture *texture = nullptr;
+ QRhiRenderBuffer *buffer = nullptr;
+ QRhiTextureRenderTarget *texTarget = nullptr;
+ QRhiRenderPassDescriptor *rpDesc = nullptr;
+#endif
+ };
+
+ virtual bool initRhi(RenderViewData &viewData);
+ virtual QImage grabRenderControl(RenderViewData &viewData);
+
private:
- QPointer<QQuickView> m_quickView;
+ RenderViewData m_viewData;
DesignerSupport m_designerSupport;
+ QQmlEngine *m_qmlEngine = nullptr;
};
} // QmlDesigner
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp
index ae167ad6ca..2a34864a84 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5previewnodeinstanceserver.cpp
@@ -71,7 +71,7 @@ void Qt5PreviewNodeInstanceServer::collectItemChangesAndSendChangeCommands()
if (!inFunction && nodeInstanceClient()->bytesToWrite() < 10000) {
inFunction = true;
- DesignerSupport::polishItems(quickView());
+ DesignerSupport::polishItems(quickWindow());
QVector<ImageContainer> imageContainerVector;
imageContainerVector.append(ImageContainer(0, renderPreviewImage(), -1));
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp
index 4a45c626be..bb1aa72445 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp
@@ -74,9 +74,9 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands()
if (!inFunction) {
inFunction = true;
- DesignerSupport::polishItems(quickView());
+ DesignerSupport::polishItems(quickWindow());
- if (quickView() && nodeInstanceClient()->bytesToWrite() < 10000) {
+ if (quickWindow() && nodeInstanceClient()->bytesToWrite() < 10000) {
foreach (QQuickItem *item, allItems()) {
if (item) {
if (hasInstanceForObject(item)) {
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5testnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5testnodeinstanceserver.cpp
index a6570b4a1e..9edb567d5b 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5testnodeinstanceserver.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5testnodeinstanceserver.cpp
@@ -257,13 +257,13 @@ void Qt5TestNodeInstanceServer::removeSharedMemory(const RemoveSharedMemoryComma
void QmlDesigner::Qt5TestNodeInstanceServer::collectItemChangesAndSendChangeCommands()
{
- DesignerSupport::polishItems(quickView());
+ DesignerSupport::polishItems(quickWindow());
QSet<ServerNodeInstance> informationChangedInstanceSet;
QVector<InstancePropertyPair> propertyChangedList;
QSet<ServerNodeInstance> parentChangedSet;
- if (quickView()) {
+ if (quickWindow()) {
foreach (QQuickItem *item, allItems()) {
if (item && hasInstanceForObject(item)) {
ServerNodeInstance instance = instanceForObject(item);
diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp
index e9e6328ce9..81607cbdd6 100644
--- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp
+++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp
@@ -174,11 +174,10 @@ void QuickItemNodeInstance::initialize(const ObjectNodeInstance::Pointer &object
InstanceContainer::NodeFlags flags)
{
- if (instanceId() == 0) {
- DesignerSupport::setRootItem(nodeInstanceServer()->quickView(), quickItem());
- } else {
- quickItem()->setParentItem(qobject_cast<QQuickItem*>(nodeInstanceServer()->quickView()->rootObject()));
- }
+ if (instanceId() == 0)
+ nodeInstanceServer()->setRootItem(quickItem());
+ else
+ quickItem()->setParentItem(nodeInstanceServer()->rootItem());
if (quickItem()->window() && checkIfRefFromEffect(instanceId())) {
designerSupport()->refFromEffectItem(quickItem(),
@@ -420,19 +419,19 @@ QImage QuickItemNodeInstance::renderImage() const
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (s_unifiedRenderPath) {
- renderImage = nodeInstanceServer()->quickView()->grabWindow();
+ renderImage = nodeInstanceServer()->quickWindow()->grabWindow();
} else {
// Fake render loop signaling to update things like QML items as 3D textures
- nodeInstanceServer()->quickView()->beforeSynchronizing();
- nodeInstanceServer()->quickView()->beforeRendering();
+ nodeInstanceServer()->quickWindow()->beforeSynchronizing();
+ nodeInstanceServer()->quickWindow()->beforeRendering();
renderImage = designerSupport()->renderImageForItem(quickItem(), renderBoundingRect, size);
- nodeInstanceServer()->quickView()->afterRendering();
+ nodeInstanceServer()->quickWindow()->afterRendering();
}
renderImage.setDevicePixelRatio(devicePixelRatio);
#else
- renderImage = nodeInstanceServer()->quickView()->grabWindow();
+ renderImage = nodeInstanceServer()->grabWindow();
renderImage = renderImage.copy(renderBoundingRect.toRect());
/* When grabbing an offscren window the device pixel ratio is 1 */
renderImage.setDevicePixelRatio(1);
@@ -452,20 +451,20 @@ QImage QuickItemNodeInstance::renderPreviewImage(const QSize &previewImageSize)
QImage image;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (s_unifiedRenderPath) {
- image = nodeInstanceServer()->quickView()->grabWindow();
+ image = nodeInstanceServer()->quickWindow()->grabWindow();
} else {
// Fake render loop signaling to update things like QML items as 3D textures
- nodeInstanceServer()->quickView()->beforeSynchronizing();
- nodeInstanceServer()->quickView()->beforeRendering();
+ nodeInstanceServer()->quickWindow()->beforeSynchronizing();
+ nodeInstanceServer()->quickWindow()->beforeRendering();
image = designerSupport()->renderImageForItem(quickItem(),
previewItemBoundingRect,
size);
- nodeInstanceServer()->quickView()->afterRendering();
+ nodeInstanceServer()->quickWindow()->afterRendering();
}
#else
- image = nodeInstanceServer()->quickView()->grabWindow();
+ image = nodeInstanceServer()->grabWindow();
image = image.copy(previewItemBoundingRect.toRect());
#endif