forked from qt-creator/qt-creator
QmlDesigner: Add InstanceImageProvider to PropertyEditor
Task-number: QDS-14768 Change-Id: I76bb54aa75e7a8a6828e7d7b75a077042301d2d2 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -412,6 +412,7 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
gradientpresetdefaultlistmodel.cpp gradientpresetdefaultlistmodel.h
|
gradientpresetdefaultlistmodel.cpp gradientpresetdefaultlistmodel.h
|
||||||
gradientpresetitem.cpp gradientpresetitem.h
|
gradientpresetitem.cpp gradientpresetitem.h
|
||||||
gradientpresetlistmodel.cpp gradientpresetlistmodel.h
|
gradientpresetlistmodel.cpp gradientpresetlistmodel.h
|
||||||
|
instanceimageprovider.cpp instanceimageprovider.h
|
||||||
propertyeditorcontextobject.cpp propertyeditorcontextobject.h
|
propertyeditorcontextobject.cpp propertyeditorcontextobject.h
|
||||||
propertyeditorqmlbackend.cpp propertyeditorqmlbackend.h
|
propertyeditorqmlbackend.cpp propertyeditorqmlbackend.h
|
||||||
propertyeditortransaction.cpp propertyeditortransaction.h
|
propertyeditortransaction.cpp propertyeditortransaction.h
|
||||||
|
@@ -905,8 +905,9 @@ void MaterialEditorView::requestPreviewRender()
|
|||||||
static int requestId = 0;
|
static int requestId = 0;
|
||||||
m_previewRequestId = QByteArray(MATERIAL_EDITOR_IMAGE_REQUEST_ID)
|
m_previewRequestId = QByteArray(MATERIAL_EDITOR_IMAGE_REQUEST_ID)
|
||||||
+ QByteArray::number(++requestId);
|
+ QByteArray::number(++requestId);
|
||||||
static_cast<const NodeInstanceView *>(model()->nodeInstanceView())
|
|
||||||
->previewImageDataForGenericNode(m_selectedMaterial, {}, m_previewSize, m_previewRequestId);
|
model()->sendCustomNotificationToNodeInstanceView(
|
||||||
|
NodePreviewImage{m_selectedMaterial, {}, m_previewSize, m_previewRequestId});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,150 @@
|
|||||||
|
// Copyright (C) 2025 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "instanceimageprovider.h"
|
||||||
|
|
||||||
|
#include <abstractview.h>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
static const char INSTANCE_IMAGE_REQUEST_ID[] = "PropertyEditor.InstanceImage";
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
InstanceImageProvider::InstanceImageProvider()
|
||||||
|
: QQuickImageProvider(Pixmap)
|
||||||
|
, m_delayTimer(new QTimer(this))
|
||||||
|
{
|
||||||
|
m_delayTimer->setInterval(500);
|
||||||
|
m_delayTimer->setSingleShot(true);
|
||||||
|
m_delayTimer->callOnTimeout([this] { requestOne(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \brief If a fresh image for the node is available, it returns it.
|
||||||
|
* Otherwise, if the requested node matches the received node, it loads a rescaled image of the
|
||||||
|
* most recent received image.
|
||||||
|
* But since it's been rescaled, and probably doesn't have a good resolution,
|
||||||
|
* it requests one more to get a new image.
|
||||||
|
* \return The most recent image received for the node from NodeInstanceView.
|
||||||
|
*/
|
||||||
|
QPixmap InstanceImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
|
||||||
|
{
|
||||||
|
using namespace Qt::StringLiterals;
|
||||||
|
static const QPixmap defaultImage = QPixmap::fromImage(
|
||||||
|
QImage(":/materialeditor/images/defaultmaterialpreview.png"));
|
||||||
|
|
||||||
|
if (id != "preview")
|
||||||
|
return defaultImage;
|
||||||
|
|
||||||
|
if (!m_requestedNode)
|
||||||
|
return defaultImage;
|
||||||
|
|
||||||
|
QPixmap result;
|
||||||
|
if (dataAvailable(m_requestedNode, requestedSize)) {
|
||||||
|
result = m_receivedImage;
|
||||||
|
} else {
|
||||||
|
result = (m_requestedNode == m_receivedNode) ? getScaledImage(requestedSize) : defaultImage;
|
||||||
|
|
||||||
|
// Here we should request one more image since the dataAvailable was false, and it means
|
||||||
|
// that we've temporarily returned a scaled image. But we need another fresh image with
|
||||||
|
// the correct size.
|
||||||
|
|
||||||
|
if (hasPendingRequest())
|
||||||
|
postponeRequest(requestedSize);
|
||||||
|
else
|
||||||
|
requestOne(requestedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.isNull())
|
||||||
|
result = defaultImage;
|
||||||
|
|
||||||
|
if (size)
|
||||||
|
*size = result.size();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceImageProvider::feedImage(const ModelNode &node,
|
||||||
|
const QPixmap &pixmap,
|
||||||
|
const QByteArray &requestId)
|
||||||
|
{
|
||||||
|
if (!requestId.startsWith(INSTANCE_IMAGE_REQUEST_ID))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (m_pendingRequest == requestId)
|
||||||
|
m_pendingRequest.clear();
|
||||||
|
|
||||||
|
m_receivedImage = pixmap;
|
||||||
|
m_receivedNode = node;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceImageProvider::setModelNode(const ModelNode &node)
|
||||||
|
{
|
||||||
|
m_requestedNode = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InstanceImageProvider::hasPendingRequest() const
|
||||||
|
{
|
||||||
|
return !m_pendingRequest.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceImageProvider::requestOne()
|
||||||
|
{
|
||||||
|
if (!m_requestedNode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
static int requestId = 0;
|
||||||
|
QByteArray previewRequestId = QByteArray(INSTANCE_IMAGE_REQUEST_ID)
|
||||||
|
+ QByteArray::number(++requestId);
|
||||||
|
m_pendingRequest = previewRequestId;
|
||||||
|
|
||||||
|
m_resetRequest = false;
|
||||||
|
|
||||||
|
m_requestedNode.model()->sendCustomNotificationToNodeInstanceView(
|
||||||
|
NodePreviewImage{m_requestedNode, {}, m_requestedSize, previewRequestId});
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceImageProvider::requestOne(QSize size)
|
||||||
|
{
|
||||||
|
prepareRequest(size);
|
||||||
|
requestOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceImageProvider::postponeRequest(QSize size)
|
||||||
|
{
|
||||||
|
prepareRequest(size);
|
||||||
|
QMetaObject::invokeMethod(m_delayTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceImageProvider::prepareRequest(QSize size)
|
||||||
|
{
|
||||||
|
m_requestedSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* \return true if the node matches the most recent node received from NodeInstanceView, and the
|
||||||
|
* size is the same as the received one, and data is not invalidated after the image is received.
|
||||||
|
*/
|
||||||
|
bool InstanceImageProvider::dataAvailable(const ModelNode &node, QSize size)
|
||||||
|
{
|
||||||
|
return !m_resetRequest && node == m_receivedNode && size == m_receivedImage.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstanceImageProvider::invalidate()
|
||||||
|
{
|
||||||
|
m_resetRequest = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap InstanceImageProvider::getScaledImage(QSize size)
|
||||||
|
{
|
||||||
|
if (size == m_receivedImage.size())
|
||||||
|
return m_receivedImage;
|
||||||
|
else
|
||||||
|
return m_receivedImage.scaled(size, Qt::KeepAspectRatioByExpanding);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,53 @@
|
|||||||
|
// Copyright (C) 2025 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <model.h>
|
||||||
|
#include <modelnode.h>
|
||||||
|
|
||||||
|
#include <QCache>
|
||||||
|
#include <QQuickImageProvider>
|
||||||
|
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QTimer)
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class InstanceImageProvider : public QQuickImageProvider
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit InstanceImageProvider();
|
||||||
|
|
||||||
|
QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override;
|
||||||
|
|
||||||
|
bool feedImage(const ModelNode &node, const QPixmap &pixmap, const QByteArray &requestId);
|
||||||
|
void setModelNode(const ModelNode &node);
|
||||||
|
|
||||||
|
bool hasPendingRequest() const;
|
||||||
|
void invalidate();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void requestOne();
|
||||||
|
void requestOne(QSize size);
|
||||||
|
void postponeRequest(QSize size);
|
||||||
|
void prepareRequest(QSize size);
|
||||||
|
bool dataAvailable(const ModelNode &node, QSize size);
|
||||||
|
|
||||||
|
QPixmap getScaledImage(QSize size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QByteArray m_pendingRequest;
|
||||||
|
bool m_resetRequest = false;
|
||||||
|
|
||||||
|
ModelNode m_requestedNode;
|
||||||
|
ModelNode m_receivedNode;
|
||||||
|
QSize m_requestedSize;
|
||||||
|
|
||||||
|
QPixmap m_receivedImage;
|
||||||
|
|
||||||
|
QTimer *m_delayTimer = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "propertyeditorqmlbackend.h"
|
#include "propertyeditorqmlbackend.h"
|
||||||
|
|
||||||
|
#include "instanceimageprovider.h"
|
||||||
#include "propertyeditortransaction.h"
|
#include "propertyeditortransaction.h"
|
||||||
#include "propertyeditorutils.h"
|
#include "propertyeditorutils.h"
|
||||||
#include "propertyeditorvalue.h"
|
#include "propertyeditorvalue.h"
|
||||||
@@ -31,12 +32,12 @@
|
|||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/qtcassert.h>
|
|
||||||
#include <utils/smallstring.h>
|
#include <utils/smallstring.h>
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QQuickItem>
|
||||||
#include <QVector2D>
|
#include <QVector2D>
|
||||||
#include <QVector3D>
|
#include <QVector3D>
|
||||||
#include <QVector4D>
|
#include <QVector4D>
|
||||||
@@ -321,6 +322,20 @@ void PropertyEditorQmlBackend::handlePropertiesRemovedInModelNodeProxy(const Abs
|
|||||||
m_backendModelNode.handlePropertiesRemoved(property);
|
m_backendModelNode.handlePropertiesRemoved(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PropertyEditorQmlBackend::handleModelNodePreviewPixmapChanged(const ModelNode &node,
|
||||||
|
const QPixmap &pixmap,
|
||||||
|
const QByteArray &requestId)
|
||||||
|
{
|
||||||
|
InstanceImageProvider *imageProvider = m_view->instanceImageProvider();
|
||||||
|
|
||||||
|
if (!imageProvider)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool imageFed = imageProvider->feedImage(node, pixmap, requestId);
|
||||||
|
if (imageFed && !imageProvider->hasPendingRequest())
|
||||||
|
refreshPreview();
|
||||||
|
}
|
||||||
|
|
||||||
void PropertyEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qmlObjectNode,
|
void PropertyEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qmlObjectNode,
|
||||||
PropertyNameView name,
|
PropertyNameView name,
|
||||||
const QVariant &value,
|
const QVariant &value,
|
||||||
@@ -591,57 +606,14 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
|
|||||||
contextObject()->setSelectedNode(qmlObjectNode);
|
contextObject()->setSelectedNode(qmlObjectNode);
|
||||||
contextObject()->setHasQuick3DImport(propertyEditor->model()->hasImport("QtQuick3D"));
|
contextObject()->setHasQuick3DImport(propertyEditor->model()->hasImport("QtQuick3D"));
|
||||||
|
|
||||||
|
m_view->instanceImageProvider()->setModelNode(propertyEditor->firstSelectedModelNode());
|
||||||
|
|
||||||
qCInfo(propertyEditorBenchmark) << "final:" << time.elapsed();
|
qCInfo(propertyEditorBenchmark) << "final:" << time.elapsed();
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "PropertyEditor: invalid node for setup";
|
qWarning() << "PropertyEditor: invalid node for setup";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyEditorQmlBackend::initialSetup(const TypeName &typeName, const QUrl &qmlSpecificsFile, PropertyEditorView *propertyEditor)
|
|
||||||
{
|
|
||||||
NodeMetaInfo metaInfo = propertyEditor->model()->metaInfo(typeName);
|
|
||||||
|
|
||||||
for (const auto &property : PropertyEditorUtils::filteredProperties(metaInfo)) {
|
|
||||||
setupPropertyEditorValue(property.name(), propertyEditor, property.propertyType());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto valueObject = qobject_cast<PropertyEditorValue *>(variantToQObject(
|
|
||||||
m_backendValuesPropertyMap.value(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY)));
|
|
||||||
if (!valueObject)
|
|
||||||
valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap);
|
|
||||||
valueObject->setName(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY);
|
|
||||||
|
|
||||||
valueObject->setValue(typeName);
|
|
||||||
QObject::connect(valueObject,
|
|
||||||
&PropertyEditorValue::valueChanged,
|
|
||||||
&backendValuesPropertyMap(),
|
|
||||||
&DesignerPropertyMap::valueChanged);
|
|
||||||
m_backendValuesPropertyMap.insert(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY,
|
|
||||||
QVariant::fromValue(valueObject));
|
|
||||||
|
|
||||||
// id
|
|
||||||
valueObject = qobject_cast<PropertyEditorValue*>(variantToQObject(m_backendValuesPropertyMap.value(QLatin1String("id"))));
|
|
||||||
if (!valueObject)
|
|
||||||
valueObject = new PropertyEditorValue(&m_backendValuesPropertyMap);
|
|
||||||
valueObject->setName("id");
|
|
||||||
valueObject->setValue("id");
|
|
||||||
QObject::connect(valueObject, &PropertyEditorValue::valueChanged, &backendValuesPropertyMap(), &DesignerPropertyMap::valueChanged);
|
|
||||||
m_backendValuesPropertyMap.insert(QLatin1String("id"), QVariant::fromValue(valueObject));
|
|
||||||
|
|
||||||
context()->setContextProperties(QVector<QQmlContext::PropertyPair>{
|
|
||||||
{{"anchorBackend"}, QVariant::fromValue(&m_backendAnchorBinding)},
|
|
||||||
{{"modelNodeBackend"}, QVariant::fromValue(&m_backendModelNode)},
|
|
||||||
{{"transaction"}, QVariant::fromValue(m_propertyEditorTransaction.get())}});
|
|
||||||
|
|
||||||
contextObject()->setSpecificsUrl(qmlSpecificsFile);
|
|
||||||
|
|
||||||
contextObject()->setStateName(QStringLiteral("basestate"));
|
|
||||||
|
|
||||||
contextObject()->setIsBaseState(true);
|
|
||||||
|
|
||||||
contextObject()->setSpecificQmlData(QStringLiteral(""));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString PropertyEditorQmlBackend::propertyEditorResourcesPath()
|
QString PropertyEditorQmlBackend::propertyEditorResourcesPath()
|
||||||
{
|
{
|
||||||
return resourcesPath("propertyEditorQmlSources");
|
return resourcesPath("propertyEditorQmlSources");
|
||||||
@@ -946,11 +918,14 @@ NodeMetaInfo PropertyEditorQmlBackend::findCommonAncestor(const ModelNode &node)
|
|||||||
|
|
||||||
AbstractView *view = node.view();
|
AbstractView *view = node.view();
|
||||||
|
|
||||||
if (view->selectedModelNodes().size() > 1) {
|
const QList<ModelNode> &selectedNodes = view->selectedModelNodes();
|
||||||
|
if (selectedNodes.size() > 1) {
|
||||||
NodeMetaInfo commonClass = node.metaInfo();
|
NodeMetaInfo commonClass = node.metaInfo();
|
||||||
for (const ModelNode ¤tNode : view->selectedModelNodes()) {
|
|
||||||
if (currentNode.metaInfo().isValid() && !currentNode.metaInfo().isBasedOn(commonClass))
|
for (const ModelNode &selectedNode : selectedNodes) {
|
||||||
commonClass = findCommonSuperClass(currentNode.metaInfo(), commonClass);
|
const NodeMetaInfo &nodeMetaInfo = selectedNode.metaInfo();
|
||||||
|
if (nodeMetaInfo.isValid() && !nodeMetaInfo.isBasedOn(commonClass))
|
||||||
|
commonClass = findCommonSuperClass(nodeMetaInfo, commonClass);
|
||||||
}
|
}
|
||||||
return commonClass;
|
return commonClass;
|
||||||
}
|
}
|
||||||
@@ -963,12 +938,22 @@ void PropertyEditorQmlBackend::refreshBackendModel()
|
|||||||
m_backendModelNode.refresh();
|
m_backendModelNode.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PropertyEditorQmlBackend::refreshPreview()
|
||||||
|
{
|
||||||
|
auto qmlPreview = widget()->rootObject();
|
||||||
|
|
||||||
|
if (qmlPreview && qmlPreview->metaObject()->indexOfMethod("refreshPreview()") > -1)
|
||||||
|
QMetaObject::invokeMethod(qmlPreview, "refreshPreview");
|
||||||
|
}
|
||||||
|
|
||||||
void PropertyEditorQmlBackend::setupContextProperties()
|
void PropertyEditorQmlBackend::setupContextProperties()
|
||||||
{
|
{
|
||||||
context()->setContextProperty("modelNodeBackend", &m_backendModelNode);
|
context()->setContextProperties({
|
||||||
context()->setContextProperties(QVector<QQmlContext::PropertyPair>{
|
{"modelNodeBackend", QVariant::fromValue(&m_backendModelNode)},
|
||||||
{{"anchorBackend"}, QVariant::fromValue(&m_backendAnchorBinding)},
|
{"anchorBackend", QVariant::fromValue(&m_backendAnchorBinding)},
|
||||||
{{"transaction"}, QVariant::fromValue(m_propertyEditorTransaction.get())}});
|
{"transaction", QVariant::fromValue(m_propertyEditorTransaction.get())},
|
||||||
|
{"dummyBackendValue", QVariant::fromValue(m_dummyPropertyEditorValue.get())},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QDS_USE_PROJECTSTORAGE
|
#ifndef QDS_USE_PROJECTSTORAGE
|
||||||
@@ -1062,14 +1047,12 @@ void PropertyEditorQmlBackend::setValueforAuxiliaryProperties(const QmlObjectNod
|
|||||||
#ifndef QDS_USE_PROJECTSTORAGE
|
#ifndef QDS_USE_PROJECTSTORAGE
|
||||||
std::tuple<QUrl, NodeMetaInfo> PropertyEditorQmlBackend::getQmlUrlForMetaInfo(const NodeMetaInfo &metaInfo)
|
std::tuple<QUrl, NodeMetaInfo> PropertyEditorQmlBackend::getQmlUrlForMetaInfo(const NodeMetaInfo &metaInfo)
|
||||||
{
|
{
|
||||||
QString className;
|
|
||||||
if (metaInfo.isValid()) {
|
if (metaInfo.isValid()) {
|
||||||
const NodeMetaInfos hierarchy = metaInfo.selfAndPrototypes();
|
const NodeMetaInfos &hierarchy = metaInfo.selfAndPrototypes();
|
||||||
for (const NodeMetaInfo &info : hierarchy) {
|
for (const NodeMetaInfo &info : hierarchy) {
|
||||||
QUrl fileUrl = fileToUrl(locateQmlFile(info, QString::fromUtf8(qmlFileName(info))));
|
QUrl fileUrl = fileToUrl(locateQmlFile(info, QString::fromUtf8(qmlFileName(info))));
|
||||||
if (fileUrl.isValid()) {
|
if (fileUrl.isValid())
|
||||||
return {fileUrl, info};
|
return {fileUrl, info};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1126,4 +1109,3 @@ QString PropertyEditorQmlBackend::locateQmlFile(const NodeMetaInfo &info, const
|
|||||||
#endif // QDS_USE_PROJECTSTORAGE
|
#endif // QDS_USE_PROJECTSTORAGE
|
||||||
|
|
||||||
} //QmlDesigner
|
} //QmlDesigner
|
||||||
|
|
||||||
|
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QQuickImageProvider)
|
||||||
|
|
||||||
class PropertyEditorValue;
|
class PropertyEditorValue;
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
@@ -37,7 +39,6 @@ public:
|
|||||||
~PropertyEditorQmlBackend();
|
~PropertyEditorQmlBackend();
|
||||||
|
|
||||||
void setup(const QmlObjectNode &fxObjectNode, const QString &stateName, const QUrl &qmlSpecificsFile, PropertyEditorView *propertyEditor);
|
void setup(const QmlObjectNode &fxObjectNode, const QString &stateName, const QUrl &qmlSpecificsFile, PropertyEditorView *propertyEditor);
|
||||||
void initialSetup(const TypeName &typeName, const QUrl &qmlSpecificsFile, PropertyEditorView *propertyEditor);
|
|
||||||
void setValue(const QmlObjectNode &fxObjectNode, PropertyNameView name, const QVariant &value);
|
void setValue(const QmlObjectNode &fxObjectNode, PropertyNameView name, const QVariant &value);
|
||||||
void setExpression(PropertyNameView propName, const QString &exp);
|
void setExpression(PropertyNameView propName, const QString &exp);
|
||||||
|
|
||||||
@@ -86,10 +87,14 @@ public:
|
|||||||
void handleVariantPropertyChangedInModelNodeProxy(const VariantProperty &property);
|
void handleVariantPropertyChangedInModelNodeProxy(const VariantProperty &property);
|
||||||
void handleBindingPropertyChangedInModelNodeProxy(const BindingProperty &property);
|
void handleBindingPropertyChangedInModelNodeProxy(const BindingProperty &property);
|
||||||
void handlePropertiesRemovedInModelNodeProxy(const AbstractProperty &property);
|
void handlePropertiesRemovedInModelNodeProxy(const AbstractProperty &property);
|
||||||
|
void handleModelNodePreviewPixmapChanged(const ModelNode &node,
|
||||||
|
const QPixmap &pixmap,
|
||||||
|
const QByteArray &requestId);
|
||||||
|
|
||||||
static NodeMetaInfo findCommonAncestor(const ModelNode &node);
|
static NodeMetaInfo findCommonAncestor(const ModelNode &node);
|
||||||
|
|
||||||
void refreshBackendModel();
|
void refreshBackendModel();
|
||||||
|
void refreshPreview();
|
||||||
|
|
||||||
void setupContextProperties();
|
void setupContextProperties();
|
||||||
|
|
||||||
|
@@ -67,8 +67,7 @@ PropertyEditorView::PropertyEditorView(AsynchronousImageCache &imageCache,
|
|||||||
, m_timerId(0)
|
, m_timerId(0)
|
||||||
, m_stackedWidget(new PropertyEditorWidget())
|
, m_stackedWidget(new PropertyEditorWidget())
|
||||||
, m_qmlBackEndForCurrentType(nullptr)
|
, m_qmlBackEndForCurrentType(nullptr)
|
||||||
, m_propertyComponentGenerator{QmlDesigner::PropertyEditorQmlBackend::propertyEditorResourcesPath(),
|
, m_propertyComponentGenerator{PropertyEditorQmlBackend::propertyEditorResourcesPath(), model()}
|
||||||
model()}
|
|
||||||
, m_locked(false)
|
, m_locked(false)
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -602,6 +601,7 @@ void PropertyEditorView::setupQmlBackend()
|
|||||||
#else
|
#else
|
||||||
const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(m_selectedNode);
|
const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(m_selectedNode);
|
||||||
|
|
||||||
|
// qmlFileUrl is panel url. and specifics is its metainfo
|
||||||
const auto [qmlFileUrl, specificsClassMetaInfo] = PropertyEditorQmlBackend::getQmlUrlForMetaInfo(
|
const auto [qmlFileUrl, specificsClassMetaInfo] = PropertyEditorQmlBackend::getQmlUrlForMetaInfo(
|
||||||
commonAncestor);
|
commonAncestor);
|
||||||
|
|
||||||
@@ -1045,6 +1045,17 @@ void PropertyEditorView::importsChanged(const Imports &addedImports, const Impor
|
|||||||
m_qmlBackEndForCurrentType->contextObject()->setHasQuick3DImport(true);
|
m_qmlBackEndForCurrentType->contextObject()->setHasQuick3DImport(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PropertyEditorView::modelNodePreviewPixmapChanged(const ModelNode &node,
|
||||||
|
const QPixmap &pixmap,
|
||||||
|
const QByteArray &requestId)
|
||||||
|
{
|
||||||
|
if (node != m_selectedNode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_qmlBackEndForCurrentType)
|
||||||
|
m_qmlBackEndForCurrentType->handleModelNodePreviewPixmapChanged(node, pixmap, requestId);
|
||||||
|
}
|
||||||
|
|
||||||
void PropertyEditorView::highlightTextureProperties(bool highlight)
|
void PropertyEditorView::highlightTextureProperties(bool highlight)
|
||||||
{
|
{
|
||||||
NodeMetaInfo metaInfo = m_selectedNode.metaInfo();
|
NodeMetaInfo metaInfo = m_selectedNode.metaInfo();
|
||||||
|
@@ -73,6 +73,10 @@ public:
|
|||||||
const NodeAbstractProperty &oldPropertyParent,
|
const NodeAbstractProperty &oldPropertyParent,
|
||||||
AbstractView::PropertyChangeFlags propertyChange) override;
|
AbstractView::PropertyChangeFlags propertyChange) override;
|
||||||
|
|
||||||
|
void modelNodePreviewPixmapChanged(const ModelNode &node,
|
||||||
|
const QPixmap &pixmap,
|
||||||
|
const QByteArray &requestId) override;
|
||||||
|
|
||||||
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
void importsChanged(const Imports &addedImports, const Imports &removedImports) override;
|
||||||
|
|
||||||
void dragStarted(QMimeData *mimeData) override;
|
void dragStarted(QMimeData *mimeData) override;
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include "gradientmodel.h"
|
#include "gradientmodel.h"
|
||||||
#include "gradientpresetcustomlistmodel.h"
|
#include "gradientpresetcustomlistmodel.h"
|
||||||
#include "gradientpresetdefaultlistmodel.h"
|
#include "gradientpresetdefaultlistmodel.h"
|
||||||
|
#include "instanceimageprovider.h"
|
||||||
#include "itemfiltermodel.h"
|
#include "itemfiltermodel.h"
|
||||||
#include "listvalidator.h"
|
#include "listvalidator.h"
|
||||||
#include "propertychangesmodel.h"
|
#include "propertychangesmodel.h"
|
||||||
@@ -40,6 +41,14 @@ Quick2PropertyEditorView::Quick2PropertyEditorView(AsynchronousImageCache &image
|
|||||||
Theme::setupTheme(engine());
|
Theme::setupTheme(engine());
|
||||||
engine()->addImageProvider("qmldesigner_thumbnails",
|
engine()->addImageProvider("qmldesigner_thumbnails",
|
||||||
new AssetImageProvider(imageCache));
|
new AssetImageProvider(imageCache));
|
||||||
|
|
||||||
|
m_instanceImageProvider = new InstanceImageProvider();
|
||||||
|
engine()->addImageProvider("nodeInstance", m_instanceImageProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
InstanceImageProvider *Quick2PropertyEditorView::instanceImageProvider() const
|
||||||
|
{
|
||||||
|
return m_instanceImageProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Quick2PropertyEditorView::registerQmlTypes()
|
void Quick2PropertyEditorView::registerQmlTypes()
|
||||||
|
@@ -5,9 +5,10 @@
|
|||||||
|
|
||||||
#include <QQuickWidget>
|
#include <QQuickWidget>
|
||||||
|
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class InstanceImageProvider;
|
||||||
|
|
||||||
class Quick2PropertyEditorView : public QQuickWidget
|
class Quick2PropertyEditorView : public QQuickWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -15,7 +16,12 @@ class Quick2PropertyEditorView : public QQuickWidget
|
|||||||
public:
|
public:
|
||||||
explicit Quick2PropertyEditorView(class AsynchronousImageCache &imageCache);
|
explicit Quick2PropertyEditorView(class AsynchronousImageCache &imageCache);
|
||||||
|
|
||||||
|
InstanceImageProvider *instanceImageProvider() const;
|
||||||
|
|
||||||
static void registerQmlTypes();
|
static void registerQmlTypes();
|
||||||
|
|
||||||
|
private:
|
||||||
|
InstanceImageProvider *m_instanceImageProvider = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} //QmlDesigner
|
} //QmlDesigner
|
||||||
|
@@ -712,10 +712,16 @@ void NodeInstanceView::customNotification(const AbstractView *view,
|
|||||||
|
|
||||||
void NodeInstanceView::customNotification(const CustomNotificationPackage &package)
|
void NodeInstanceView::customNotification(const CustomNotificationPackage &package)
|
||||||
{
|
{
|
||||||
if (auto inputEvent = std::get_if<InputEvent>(&package))
|
if (auto inputEvent = std::get_if<InputEvent>(&package)) {
|
||||||
sendInputEvent(inputEvent->event);
|
sendInputEvent(inputEvent->event);
|
||||||
else if (auto resize3DCanvas = std::get_if<Resize3DCanvas>(&package))
|
} else if (auto resize3DCanvas = std::get_if<Resize3DCanvas>(&package)) {
|
||||||
edit3DViewResized(resize3DCanvas->size);
|
edit3DViewResized(resize3DCanvas->size);
|
||||||
|
} else if (auto preview = std::get_if<NodePreviewImage>(&package)) {
|
||||||
|
previewImageDataForGenericNode(preview->modelNode,
|
||||||
|
preview->renderNode,
|
||||||
|
preview->size,
|
||||||
|
preview->requestId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::nodeSourceChanged(const ModelNode &node, const QString & newNodeSource)
|
void NodeInstanceView::nodeSourceChanged(const ModelNode &node, const QString & newNodeSource)
|
||||||
|
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "modelnode.h"
|
||||||
|
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
|
|
||||||
@@ -18,6 +20,14 @@ struct Resize3DCanvas
|
|||||||
QSize size;
|
QSize size;
|
||||||
};
|
};
|
||||||
|
|
||||||
using CustomNotificationPackage = std::variant<InputEvent, Resize3DCanvas>;
|
struct NodePreviewImage
|
||||||
|
{
|
||||||
|
ModelNode modelNode;
|
||||||
|
ModelNode renderNode;
|
||||||
|
QSize size;
|
||||||
|
QByteArray requestId;
|
||||||
|
};
|
||||||
|
|
||||||
|
using CustomNotificationPackage = std::variant<InputEvent, Resize3DCanvas, NodePreviewImage>;
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
Reference in New Issue
Block a user