diff --git a/share/qtcreator/qml/qmlpuppet/commands/requestmodelnodepreviewimagecommand.cpp b/share/qtcreator/qml/qmlpuppet/commands/requestmodelnodepreviewimagecommand.cpp index 17f3a65a136..265b7fd9178 100644 --- a/share/qtcreator/qml/qmlpuppet/commands/requestmodelnodepreviewimagecommand.cpp +++ b/share/qtcreator/qml/qmlpuppet/commands/requestmodelnodepreviewimagecommand.cpp @@ -32,10 +32,13 @@ namespace QmlDesigner { RequestModelNodePreviewImageCommand::RequestModelNodePreviewImageCommand() = default; -RequestModelNodePreviewImageCommand::RequestModelNodePreviewImageCommand(qint32 id, const QSize &size, const QString &componentPath) +RequestModelNodePreviewImageCommand::RequestModelNodePreviewImageCommand(qint32 id, const QSize &size, + const QString &componentPath, + qint32 renderItemId) : m_instanceId(id) , m_size(size) , m_componentPath(componentPath) + , m_renderItemId(renderItemId) { } @@ -54,11 +57,17 @@ QString RequestModelNodePreviewImageCommand::componentPath() const return m_componentPath; } +qint32 RequestModelNodePreviewImageCommand::renderItemId() const +{ + return m_renderItemId; +} + QDataStream &operator<<(QDataStream &out, const RequestModelNodePreviewImageCommand &command) { out << int(command.instanceId()); out << command.size(); out << command.componentPath(); + out << command.renderItemId(); return out; } @@ -68,6 +77,7 @@ QDataStream &operator>>(QDataStream &in, RequestModelNodePreviewImageCommand &co in >> command.m_instanceId; in >> command.m_size; in >> command.m_componentPath; + in >> command.m_renderItemId; return in; } @@ -76,7 +86,8 @@ QDebug operator <<(QDebug debug, const RequestModelNodePreviewImageCommand &comm return debug.nospace() << "RequestModelNodePreviewImageCommand(" << "instanceId: " << command.instanceId() << ", " << "size: " << command.size() << ", " - << "componentPath: " << command.componentPath() << ")"; + << "componentPath: " << command.componentPath() << ", " + << "renderItemId: " << command.renderItemId() << ")"; } } // namespace QmlDesigner diff --git a/share/qtcreator/qml/qmlpuppet/commands/requestmodelnodepreviewimagecommand.h b/share/qtcreator/qml/qmlpuppet/commands/requestmodelnodepreviewimagecommand.h index 14ebe6156ff..91ef0eddbaa 100644 --- a/share/qtcreator/qml/qmlpuppet/commands/requestmodelnodepreviewimagecommand.h +++ b/share/qtcreator/qml/qmlpuppet/commands/requestmodelnodepreviewimagecommand.h @@ -40,16 +40,19 @@ class RequestModelNodePreviewImageCommand public: RequestModelNodePreviewImageCommand(); - explicit RequestModelNodePreviewImageCommand(qint32 id, const QSize &size, const QString &componentPath); + explicit RequestModelNodePreviewImageCommand(qint32 id, const QSize &size, + const QString &componentPath, qint32 renderItemId); qint32 instanceId() const; QSize size() const; QString componentPath() const; + qint32 renderItemId() const; private: qint32 m_instanceId; QSize m_size; QString m_componentPath; + qint32 m_renderItemId; }; QDataStream &operator<<(QDataStream &out, const RequestModelNodePreviewImageCommand &command); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 944bb63c548..2963119deff 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -518,7 +518,12 @@ void Qt5InformationNodeInstanceServer::renderModelNodeImageView() void Qt5InformationNodeInstanceServer::doRenderModelNodeImageView() { - ServerNodeInstance instance = instanceForId(m_modelNodePreviewImageCommand.instanceId()); + ServerNodeInstance instance; + if (m_modelNodePreviewImageCommand.renderItemId() >= 0) + instance = instanceForId(m_modelNodePreviewImageCommand.renderItemId()); + else + instance = instanceForId(m_modelNodePreviewImageCommand.instanceId()); + if (instance.isSubclassOf("QQuick3DObject")) doRenderModelNode3DImageView(); else if (instance.isSubclassOf("QQuickItem")) diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp index e77fcb33561..f76542d3789 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp @@ -1522,7 +1522,7 @@ void removeGroup(const SelectionContext &selectionContext) QVariant previewImageDataForGenericNode(const ModelNode &modelNode) { if (modelNode.isValid()) - return modelNode.model()->nodeInstanceView()->previewImageDataForGenericNode(modelNode); + return modelNode.model()->nodeInstanceView()->previewImageDataForGenericNode(modelNode, {}); return {}; } diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h index 13818786974..e656f5a89c4 100644 --- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h +++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h @@ -138,12 +138,12 @@ public: void sendInputEvent(QInputEvent *e) const; void view3DAction(const View3DActionCommand &command); - void requestModelNodePreviewImage(const ModelNode &node); + void requestModelNodePreviewImage(const ModelNode &node, const ModelNode &renderNode); void edit3DViewResized(const QSize &size) const; void handlePuppetToCreatorCommand(const PuppetToCreatorCommand &command) override; - QVariant previewImageDataForGenericNode(const ModelNode &modelNode); + QVariant previewImageDataForGenericNode(const ModelNode &modelNode, const ModelNode &renderNode); QVariant previewImageDataForImageNode(const ModelNode &modelNode); protected: diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index 2afbffc3ddc..57d59584ffb 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -79,6 +79,7 @@ #include #include #include +#include #ifndef QMLDESIGNER_TEST #include @@ -1522,20 +1523,28 @@ void NodeInstanceView::view3DAction(const View3DActionCommand &command) m_nodeInstanceServer->view3DAction(command); } -void NodeInstanceView::requestModelNodePreviewImage(const ModelNode &node) +void NodeInstanceView::requestModelNodePreviewImage(const ModelNode &node, const ModelNode &renderNode) { if (node.isValid()) { auto instance = instanceForModelNode(node); if (instance.isValid()) { + qint32 renderItemId = -1; QString componentPath; - if (node.isComponent()) + if (renderNode.isValid()) { + auto renderInstance = instanceForModelNode(renderNode); + if (renderInstance.isValid()) + renderItemId = renderInstance.instanceId(); + if (renderNode.isComponent()) + componentPath = renderNode.metaInfo().componentFileName(); + } else if (node.isComponent()) { componentPath = node.metaInfo().componentFileName(); + } m_nodeInstanceServer->requestModelNodePreviewImage( RequestModelNodePreviewImageCommand( instance.instanceId(), QSize(Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS, Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS), - componentPath)); + componentPath, renderItemId)); } } } @@ -1562,15 +1571,17 @@ static QHash> imageDataMap; static QVariant imageDataToVariant(const ImageData &imageData) { - if (!imageData.pixmap.isNull()) { - QVariantMap map; - map.insert("type", imageData.type); + static const QPixmap placeHolder(":/navigator/icon/tooltip_placeholder.png"); + + QVariantMap map; + map.insert("type", imageData.type); + if (imageData.pixmap.isNull()) + map.insert("pixmap", placeHolder); + else map.insert("pixmap", QVariant::fromValue(imageData.pixmap)); - map.insert("id", imageData.id); - map.insert("info", imageData.info); - return map; - } - return {}; + map.insert("id", imageData.id); + map.insert("info", imageData.info); + return map; } QVariant NodeInstanceView::previewImageDataForImageNode(const ModelNode &modelNode) @@ -1583,54 +1594,79 @@ QVariant NodeInstanceView::previewImageDataForImageNode(const ModelNode &modelNo VariantProperty prop = modelNode.variantProperty("source"); QString imageSource = prop.value().toString(); - QFileInfo imageFi(imageSource); - if (imageFi.isRelative()) - imageSource = QFileInfo(modelNode.model()->fileUrl().toLocalFile()).dir().absoluteFilePath(imageSource); - - imageFi = QFileInfo(imageSource); - QDateTime modified = imageFi.lastModified(); ImageData imageData; - bool reload = true; - if (localDataMap.contains(imageSource)) { - imageData = localDataMap[imageSource]; - if (modified == imageData.time) - reload = false; - } + imageData.id = modelNode.id(); + imageData.type = QString::fromLatin1(modelNode.type()); - if (reload) { - QPixmap originalPixmap; - originalPixmap.load(imageSource); - if (!originalPixmap.isNull()) { - imageData.pixmap = originalPixmap.scaled(Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2, - Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2, - Qt::KeepAspectRatio); - imageData.pixmap.setDevicePixelRatio(2.); - - double imgSize = double(imageFi.size()); - imageData.type = QStringLiteral("%1 (%2)").arg(QString::fromLatin1(modelNode.type())).arg(imageFi.suffix()); - imageData.id = modelNode.id(); - static QStringList units({QObject::tr("B"), QObject::tr("KB"), QObject::tr("MB"), QObject::tr("GB")}); - int unitIndex = 0; - while (imgSize > 1024. && unitIndex < units.size() - 1) { - ++unitIndex; - imgSize /= 1024.; + if (imageSource.isEmpty() && modelNode.isSubclassOf("QtQuick3D.Texture")) { + // Texture node may have sourceItem instead + BindingProperty binding = modelNode.bindingProperty("sourceItem"); + if (binding.isValid()) { + ModelNode boundNode = binding.resolveToModelNode(); + if (boundNode.isValid()) { + // If bound node is a component, fall back to component render mechanism, as + // QmlItemNode::instanceRenderPixmap() often includes unnecessary empty space + // for those + if (boundNode.isComponent()) { + return previewImageDataForGenericNode(modelNode, boundNode); + } else { + QmlItemNode itemNode(boundNode); + imageData.pixmap = itemNode.instanceRenderPixmap().scaled( + Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2, + Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2, + Qt::KeepAspectRatio); + imageData.pixmap.setDevicePixelRatio(2.); + } + imageData.info = QObject::tr("Source item: %1").arg(boundNode.id()); + } + } + } else { + QFileInfo imageFi(imageSource); + if (imageFi.isRelative()) + imageSource = QFileInfo(modelNode.model()->fileUrl().toLocalFile()).dir().absoluteFilePath(imageSource); + + imageFi = QFileInfo(imageSource); + QDateTime modified = imageFi.lastModified(); + + bool reload = true; + if (localDataMap.contains(imageSource)) { + imageData = localDataMap[imageSource]; + if (modified == imageData.time) + reload = false; + } + + if (reload) { + QPixmap originalPixmap; + originalPixmap.load(imageSource); + if (!originalPixmap.isNull()) { + imageData.pixmap = originalPixmap.scaled(Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2, + Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2, + Qt::KeepAspectRatio); + imageData.pixmap.setDevicePixelRatio(2.); + + double imgSize = double(imageFi.size()); + static QStringList units({QObject::tr("B"), QObject::tr("KB"), QObject::tr("MB"), QObject::tr("GB")}); + int unitIndex = 0; + while (imgSize > 1024. && unitIndex < units.size() - 1) { + ++unitIndex; + imgSize /= 1024.; + } + imageData.info = QStringLiteral("%1 x %2\n%3%4 (%5)").arg(originalPixmap.width()).arg(originalPixmap.height()) + .arg(QString::number(imgSize, 'g', 3)).arg(units[unitIndex]).arg(imageFi.suffix()); + localDataMap.insert(imageSource, imageData); } - imageData.info = QStringLiteral("%1 x %2 (%3%4)").arg(originalPixmap.width()).arg(originalPixmap.height()) - .arg(QString::number(imgSize, 'g', 3)).arg(units[unitIndex]); - localDataMap.insert(imageSource, imageData); } } return imageDataToVariant(imageData); } -QVariant NodeInstanceView::previewImageDataForGenericNode(const ModelNode &modelNode) +QVariant NodeInstanceView::previewImageDataForGenericNode(const ModelNode &modelNode, const ModelNode &renderNode) { QFileInfo docFi = QFileInfo(modelNode.model()->fileUrl().toLocalFile()); QHash &localDataMap = imageDataMap[docFi.absoluteFilePath()]; ImageData imageData; - static const QPixmap placeHolder(":/navigator/icon/tooltip_placeholder.png"); // We need puppet to generate the image, which needs to be asynchronous. // Until the image is ready, we show a placeholder @@ -1640,10 +1676,9 @@ QVariant NodeInstanceView::previewImageDataForGenericNode(const ModelNode &model } else { imageData.type = QString::fromLatin1(modelNode.type()); imageData.id = id; - imageData.pixmap = placeHolder; localDataMap.insert(id, imageData); } - requestModelNodePreviewImage(modelNode); + requestModelNodePreviewImage(modelNode, renderNode); return imageDataToVariant(imageData); }