forked from qt-creator/qt-creator
PropertyEditor: Forward currentNodes to backend
Since PropertyEditor has introduced `selection locking feature`, it should keep its own selection for the cases that the change should affect multiple nodes. It means that model selected node might be different than the propertyEditor working nodes. Also model selection changes should be notified separately. Change-Id: I692414811369680e16b3e25213bfa4b683576c55 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -23,6 +23,7 @@ Rectangle {
|
|||||||
style: StudioTheme.Values.viewBarButtonStyle
|
style: StudioTheme.Values.viewBarButtonStyle
|
||||||
buttonIcon: StudioTheme.Constants.apply_medium
|
buttonIcon: StudioTheme.Constants.apply_medium
|
||||||
tooltip: qsTr("Apply material to selected model.")
|
tooltip: qsTr("Apply material to selected model.")
|
||||||
|
enabled: has3DModelSelected
|
||||||
onClicked: root.backend.toolBarAction(QmlMaterialNodeProxy.ApplyToSelected)
|
onClicked: root.backend.toolBarAction(QmlMaterialNodeProxy.ApplyToSelected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -164,7 +164,7 @@ Section {
|
|||||||
id: toolTipArea
|
id: toolTipArea
|
||||||
enabled: !modelNodeBackend.multiSelection && anchorBackend.hasParent
|
enabled: !modelNodeBackend.multiSelection && anchorBackend.hasParent
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: toogleExportAlias()
|
onClicked: toggleExportAlias()
|
||||||
tooltip: qsTr("Exports this component as an alias property of the root component.")
|
tooltip: qsTr("Exports this component as an alias property of the root component.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -222,7 +222,7 @@ void MaterialEditorQmlBackend::setup(const QmlObjectNode &selectedMaterialNode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// model node
|
// model node
|
||||||
m_backendModelNode.setup(selectedMaterialNode.modelNode());
|
m_backendModelNode.setup(selectedMaterialNode);
|
||||||
context()->setContextProperty("modelNodeBackend", &m_backendModelNode);
|
context()->setContextProperty("modelNodeBackend", &m_backendModelNode);
|
||||||
context()->setContextProperty("hasMaterial", QVariant(true));
|
context()->setContextProperty("hasMaterial", QVariant(true));
|
||||||
|
|
||||||
|
@@ -138,7 +138,7 @@ QStringList PropertyEditorContextObject::autoComplete(const QString &text, int p
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyEditorContextObject::toogleExportAlias()
|
void PropertyEditorContextObject::toggleExportAlias()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_model && m_model->rewriterView(), return);
|
QTC_ASSERT(m_model && m_model->rewriterView(), return);
|
||||||
|
|
||||||
@@ -156,13 +156,13 @@ void PropertyEditorContextObject::toogleExportAlias()
|
|||||||
PropertyName modelNodeId = selectedNode.id().toUtf8();
|
PropertyName modelNodeId = selectedNode.id().toUtf8();
|
||||||
ModelNode rootModelNode = rewriterView->rootModelNode();
|
ModelNode rootModelNode = rewriterView->rootModelNode();
|
||||||
|
|
||||||
rewriterView->executeInTransaction("PropertyEditorContextObject:toogleExportAlias", [&objectNode, &rootModelNode, modelNodeId](){
|
rewriterView->executeInTransaction("PropertyEditorContextObject:toggleExportAlias",
|
||||||
if (!objectNode.isAliasExported())
|
[&objectNode, &rootModelNode, modelNodeId]() {
|
||||||
objectNode.ensureAliasExport();
|
if (!objectNode.isAliasExported())
|
||||||
else
|
objectNode.ensureAliasExport();
|
||||||
if (rootModelNode.hasProperty(modelNodeId))
|
else if (rootModelNode.hasProperty(modelNodeId))
|
||||||
rootModelNode.removeProperty(modelNodeId);
|
rootModelNode.removeProperty(modelNodeId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ void PropertyEditorContextObject::changeTypeName(const QString &typeName)
|
|||||||
try {
|
try {
|
||||||
auto transaction = RewriterTransaction(rewriterView, "PropertyEditorContextObject:changeTypeName");
|
auto transaction = RewriterTransaction(rewriterView, "PropertyEditorContextObject:changeTypeName");
|
||||||
|
|
||||||
ModelNodes selectedNodes = rewriterView->selectedModelNodes(); // TODO: replace it by PropertyEditorView::currentNodes()
|
ModelNodes selectedNodes = m_editorNodes;
|
||||||
for (ModelNode &selectedNode : selectedNodes)
|
for (ModelNode &selectedNode : selectedNodes)
|
||||||
changeNodeTypeName(selectedNode);
|
changeNodeTypeName(selectedNode);
|
||||||
|
|
||||||
@@ -489,9 +489,9 @@ bool PropertyEditorContextObject::hasQuick3DImport() const
|
|||||||
return m_hasQuick3DImport;
|
return m_hasQuick3DImport;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyEditorContextObject::setSelectedNode(const ModelNode &node)
|
void PropertyEditorContextObject::setEditorNodes(const ModelNodes &nodes)
|
||||||
{
|
{
|
||||||
m_selectedNode = node;
|
m_editorNodes = nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyEditorContextObject::setHasQuick3DImport(bool value)
|
void PropertyEditorContextObject::setHasQuick3DImport(bool value)
|
||||||
@@ -531,18 +531,18 @@ void PropertyEditorContextObject::setIsQt6Project(bool value)
|
|||||||
emit isQt6ProjectChanged();
|
emit isQt6ProjectChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PropertyEditorContextObject::has3DModelSelection() const
|
bool PropertyEditorContextObject::has3DModelSelected() const
|
||||||
{
|
{
|
||||||
return m_has3DModelSelection;
|
return m_has3DModelSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyEditorContextObject::set3DHasModelSelection(bool value)
|
void PropertyEditorContextObject::setHas3DModelSelected(bool value)
|
||||||
{
|
{
|
||||||
if (value == m_has3DModelSelection)
|
if (value == m_has3DModelSelected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_has3DModelSelection = value;
|
m_has3DModelSelected = value;
|
||||||
emit has3DModelSelectionChanged();
|
emit has3DModelSelectedChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyEditorContextObject::setSpecificsUrl(const QUrl &newSpecificsUrl)
|
void PropertyEditorContextObject::setSpecificsUrl(const QUrl &newSpecificsUrl)
|
||||||
|
@@ -57,7 +57,7 @@ class PropertyEditorContextObject : public QObject
|
|||||||
Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport NOTIFY hasQuick3DImportChanged)
|
Q_PROPERTY(bool hasQuick3DImport READ hasQuick3DImport NOTIFY hasQuick3DImportChanged)
|
||||||
Q_PROPERTY(bool hasMaterialLibrary READ hasMaterialLibrary NOTIFY hasMaterialLibraryChanged)
|
Q_PROPERTY(bool hasMaterialLibrary READ hasMaterialLibrary NOTIFY hasMaterialLibraryChanged)
|
||||||
Q_PROPERTY(bool isQt6Project READ isQt6Project NOTIFY isQt6ProjectChanged)
|
Q_PROPERTY(bool isQt6Project READ isQt6Project NOTIFY isQt6ProjectChanged)
|
||||||
Q_PROPERTY(bool has3DModelSelection READ has3DModelSelection NOTIFY has3DModelSelectionChanged)
|
Q_PROPERTY(bool has3DModelSelected READ has3DModelSelected NOTIFY has3DModelSelectedChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PropertyEditorContextObject(QQuickWidget *widget, QObject *parent = nullptr);
|
PropertyEditorContextObject(QQuickWidget *widget, QObject *parent = nullptr);
|
||||||
@@ -78,7 +78,7 @@ public:
|
|||||||
|
|
||||||
Q_INVOKABLE QStringList autoComplete(const QString &text, int pos, bool explicitComplete, bool filter);
|
Q_INVOKABLE QStringList autoComplete(const QString &text, int pos, bool explicitComplete, bool filter);
|
||||||
|
|
||||||
Q_INVOKABLE void toogleExportAlias();
|
Q_INVOKABLE void toggleExportAlias();
|
||||||
|
|
||||||
Q_INVOKABLE void goIntoComponent();
|
Q_INVOKABLE void goIntoComponent();
|
||||||
|
|
||||||
@@ -142,10 +142,10 @@ public:
|
|||||||
bool isQt6Project() const;
|
bool isQt6Project() const;
|
||||||
void setIsQt6Project(bool value);
|
void setIsQt6Project(bool value);
|
||||||
|
|
||||||
bool has3DModelSelection() const;
|
bool has3DModelSelected() const;
|
||||||
void set3DHasModelSelection(bool value);
|
void setHas3DModelSelected(bool value);
|
||||||
|
|
||||||
void setSelectedNode(const ModelNode &node);
|
void setEditorNodes(const ModelNodes &nodes);
|
||||||
|
|
||||||
void setIsSelectionLocked(bool lock);
|
void setIsSelectionLocked(bool lock);
|
||||||
bool isSelectionLocked() const;
|
bool isSelectionLocked() const;
|
||||||
@@ -169,7 +169,7 @@ signals:
|
|||||||
void hasMultiSelectionChanged();
|
void hasMultiSelectionChanged();
|
||||||
void hasQuick3DImportChanged();
|
void hasQuick3DImportChanged();
|
||||||
void hasMaterialLibraryChanged();
|
void hasMaterialLibraryChanged();
|
||||||
void has3DModelSelectionChanged();
|
void has3DModelSelectedChanged();
|
||||||
void isQt6ProjectChanged();
|
void isQt6ProjectChanged();
|
||||||
void isSelectionLockedChanged();
|
void isSelectionLockedChanged();
|
||||||
|
|
||||||
@@ -217,7 +217,7 @@ private:
|
|||||||
|
|
||||||
bool m_hasQuick3DImport = false;
|
bool m_hasQuick3DImport = false;
|
||||||
bool m_hasMaterialLibrary = false;
|
bool m_hasMaterialLibrary = false;
|
||||||
bool m_has3DModelSelection = false;
|
bool m_has3DModelSelected = false;
|
||||||
bool m_isQt6Project = false;
|
bool m_isQt6Project = false;
|
||||||
|
|
||||||
QQmlComponent *m_qmlComponent;
|
QQmlComponent *m_qmlComponent;
|
||||||
@@ -240,7 +240,7 @@ private:
|
|||||||
bool m_insightEnabled = false;
|
bool m_insightEnabled = false;
|
||||||
QStringList m_insightCategories;
|
QStringList m_insightCategories;
|
||||||
|
|
||||||
ModelNode m_selectedNode;
|
ModelNodes m_editorNodes; // Nodes that are being edited by PropertyEditor
|
||||||
};
|
};
|
||||||
|
|
||||||
class EasingCurveEditor : public QObject
|
class EasingCurveEditor : public QObject
|
||||||
|
@@ -375,6 +375,12 @@ void PropertyEditorQmlBackend::handleModelNodePreviewPixmapChanged(const ModelNo
|
|||||||
refreshPreview();
|
refreshPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PropertyEditorQmlBackend::handleModelSelectedNodesChanged(PropertyEditorView *propertyEditor)
|
||||||
|
{
|
||||||
|
contextObject()->setHas3DModelSelected(!Utils3D::getSelectedModels(propertyEditor).isEmpty());
|
||||||
|
m_backendTextureNode.updateSelectionDetails();
|
||||||
|
}
|
||||||
|
|
||||||
void PropertyEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qmlObjectNode,
|
void PropertyEditorQmlBackend::createPropertyEditorValue(const QmlObjectNode &qmlObjectNode,
|
||||||
PropertyNameView name,
|
PropertyNameView name,
|
||||||
const QVariant &value,
|
const QVariant &value,
|
||||||
@@ -566,108 +572,107 @@ void PropertyEditorQmlBackend::updateInstanceImage()
|
|||||||
refreshPreview();
|
refreshPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const QString &stateName, const QUrl &qmlSpecificsFile, PropertyEditorView *propertyEditor)
|
void PropertyEditorQmlBackend::setup(const ModelNodes &editorNodes,
|
||||||
|
const QString &stateName,
|
||||||
|
const QUrl &qmlSpecificsFile,
|
||||||
|
PropertyEditorView *propertyEditor)
|
||||||
{
|
{
|
||||||
if (qmlObjectNode.isValid()) {
|
QmlObjectNode qmlObjectNode(editorNodes.isEmpty() ? ModelNode{} : editorNodes.first());
|
||||||
m_contextObject->setModel(propertyEditor->model());
|
if (!qmlObjectNode.isValid()) {
|
||||||
|
qWarning() << "PropertyEditor: invalid node for setup";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
qCInfo(propertyEditorBenchmark) << Q_FUNC_INFO;
|
m_contextObject->setModel(propertyEditor->model());
|
||||||
|
|
||||||
QElapsedTimer time;
|
qCInfo(propertyEditorBenchmark) << Q_FUNC_INFO;
|
||||||
if (propertyEditorBenchmark().isInfoEnabled())
|
|
||||||
time.start();
|
|
||||||
|
|
||||||
createPropertyEditorValues(qmlObjectNode, propertyEditor);
|
QElapsedTimer time;
|
||||||
setupLayoutAttachedProperties(qmlObjectNode, propertyEditor);
|
if (propertyEditorBenchmark().isInfoEnabled())
|
||||||
setupInsightAttachedProperties(qmlObjectNode, propertyEditor);
|
time.start();
|
||||||
setupAuxiliaryProperties(qmlObjectNode, propertyEditor);
|
|
||||||
|
|
||||||
// model node
|
createPropertyEditorValues(qmlObjectNode, propertyEditor);
|
||||||
m_backendModelNode.setup(qmlObjectNode.modelNode());
|
setupLayoutAttachedProperties(qmlObjectNode, propertyEditor);
|
||||||
context()->setContextProperty("modelNodeBackend", &m_backendModelNode);
|
setupInsightAttachedProperties(qmlObjectNode, propertyEditor);
|
||||||
|
setupAuxiliaryProperties(qmlObjectNode, propertyEditor);
|
||||||
|
|
||||||
m_backendMaterialNode.setup(qmlObjectNode);
|
// model node
|
||||||
m_backendTextureNode.setup(qmlObjectNode);
|
m_backendModelNode.setup(editorNodes);
|
||||||
|
context()->setContextProperty("modelNodeBackend", &m_backendModelNode);
|
||||||
|
|
||||||
insertValue(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY,
|
m_backendMaterialNode.setup(editorNodes);
|
||||||
m_backendModelNode.simplifiedTypeName(),
|
m_backendTextureNode.setup(qmlObjectNode);
|
||||||
qmlObjectNode.modelNode());
|
|
||||||
|
|
||||||
insertValue("id"_L1, m_backendModelNode.nodeId());
|
insertValue(Constants::PROPERTY_EDITOR_CLASSNAME_PROPERTY,
|
||||||
insertValue("objectName"_L1, m_backendModelNode.nodeObjectName());
|
m_backendModelNode.simplifiedTypeName(),
|
||||||
|
qmlObjectNode.modelNode());
|
||||||
|
|
||||||
QmlItemNode itemNode(qmlObjectNode.modelNode());
|
insertValue("id"_L1, m_backendModelNode.nodeId());
|
||||||
|
insertValue("objectName"_L1, m_backendModelNode.nodeObjectName());
|
||||||
|
|
||||||
// anchors
|
QmlItemNode itemNode(qmlObjectNode.modelNode());
|
||||||
m_backendAnchorBinding.setup(qmlObjectNode.modelNode());
|
|
||||||
setupContextProperties();
|
|
||||||
|
|
||||||
contextObject()->setHasMultiSelection(
|
// anchors
|
||||||
!qmlObjectNode.view()->singleSelectedModelNode().isValid());
|
m_backendAnchorBinding.setup(qmlObjectNode.modelNode());
|
||||||
|
setupContextProperties();
|
||||||
|
|
||||||
qCInfo(propertyEditorBenchmark) << "anchors:" << time.elapsed();
|
contextObject()->setHasMultiSelection(m_backendModelNode.multiSelection());
|
||||||
|
|
||||||
qCInfo(propertyEditorBenchmark) << "context:" << time.elapsed();
|
qCInfo(propertyEditorBenchmark) << "anchors:" << time.elapsed();
|
||||||
|
|
||||||
contextObject()->setSpecificsUrl(qmlSpecificsFile);
|
qCInfo(propertyEditorBenchmark) << "context:" << time.elapsed();
|
||||||
|
|
||||||
qCInfo(propertyEditorBenchmark) << "specifics:" << time.elapsed();
|
contextObject()->setSpecificsUrl(qmlSpecificsFile);
|
||||||
|
|
||||||
contextObject()->setStateName(stateName);
|
qCInfo(propertyEditorBenchmark) << "specifics:" << time.elapsed();
|
||||||
if (!qmlObjectNode.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
context()->setContextProperty(QLatin1String("propertyCount"),
|
contextObject()->setStateName(stateName);
|
||||||
QVariant(qmlObjectNode.modelNode().properties().size()));
|
|
||||||
|
|
||||||
QStringList stateNames = qmlObjectNode.allStateNames();
|
context()->setContextProperty(QLatin1String("propertyCount"),
|
||||||
stateNames.prepend("base state");
|
QVariant(qmlObjectNode.modelNode().properties().size()));
|
||||||
contextObject()->setAllStateNames(stateNames);
|
|
||||||
|
|
||||||
contextObject()->setIsBaseState(qmlObjectNode.isInBaseState());
|
QStringList stateNames = qmlObjectNode.allStateNames();
|
||||||
|
stateNames.prepend("base state");
|
||||||
|
contextObject()->setAllStateNames(stateNames);
|
||||||
|
|
||||||
contextObject()->setHasAliasExport(qmlObjectNode.isAliasExported());
|
contextObject()->setIsBaseState(qmlObjectNode.isInBaseState());
|
||||||
|
|
||||||
contextObject()->setHasActiveTimeline(QmlTimeline::hasActiveTimeline(qmlObjectNode.view()));
|
contextObject()->setHasAliasExport(qmlObjectNode.isAliasExported());
|
||||||
|
|
||||||
contextObject()->setSelectionChanged(false);
|
contextObject()->setHasActiveTimeline(QmlTimeline::hasActiveTimeline(qmlObjectNode.view()));
|
||||||
|
|
||||||
contextObject()->setSelectionChanged(false);
|
contextObject()->setSelectionChanged(false);
|
||||||
|
|
||||||
NodeMetaInfo metaInfo = qmlObjectNode.modelNode().metaInfo();
|
NodeMetaInfo metaInfo = qmlObjectNode.modelNode().metaInfo();
|
||||||
|
|
||||||
#ifdef QDS_USE_PROJECTSTORAGE
|
#ifdef QDS_USE_PROJECTSTORAGE
|
||||||
|
contextObject()->setMajorVersion(-1);
|
||||||
|
contextObject()->setMinorVersion(-1);
|
||||||
|
contextObject()->setMajorQtQuickVersion(-1);
|
||||||
|
contextObject()->setMinorQtQuickVersion(-1);
|
||||||
|
#else
|
||||||
|
if (metaInfo.isValid()) {
|
||||||
|
contextObject()->setMajorVersion(metaInfo.majorVersion());
|
||||||
|
contextObject()->setMinorVersion(metaInfo.minorVersion());
|
||||||
|
} else {
|
||||||
contextObject()->setMajorVersion(-1);
|
contextObject()->setMajorVersion(-1);
|
||||||
contextObject()->setMinorVersion(-1);
|
contextObject()->setMinorVersion(-1);
|
||||||
contextObject()->setMajorQtQuickVersion(-1);
|
contextObject()->setMajorQtQuickVersion(-1);
|
||||||
contextObject()->setMinorQtQuickVersion(-1);
|
contextObject()->setMinorQtQuickVersion(-1);
|
||||||
#else
|
|
||||||
if (metaInfo.isValid()) {
|
|
||||||
contextObject()->setMajorVersion(metaInfo.majorVersion());
|
|
||||||
contextObject()->setMinorVersion(metaInfo.minorVersion());
|
|
||||||
} else {
|
|
||||||
contextObject()->setMajorVersion(-1);
|
|
||||||
contextObject()->setMinorVersion(-1);
|
|
||||||
contextObject()->setMajorQtQuickVersion(-1);
|
|
||||||
contextObject()->setMinorQtQuickVersion(-1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
contextObject()->setMajorQtQuickVersion(qmlObjectNode.view()->majorQtQuickVersion());
|
|
||||||
contextObject()->setMinorQtQuickVersion(qmlObjectNode.view()->minorQtQuickVersion());
|
|
||||||
|
|
||||||
contextObject()->setHasMaterialLibrary(Utils3D::materialLibraryNode(propertyEditor).isValid());
|
|
||||||
contextObject()->setIsQt6Project(propertyEditor->externalDependencies().isQt6Project());
|
|
||||||
contextObject()->set3DHasModelSelection(!Utils3D::getSelectedModels(propertyEditor).isEmpty());
|
|
||||||
contextObject()->setSelectedNode(qmlObjectNode);
|
|
||||||
contextObject()->setHasQuick3DImport(propertyEditor->model()->hasImport("QtQuick3D"));
|
|
||||||
|
|
||||||
m_view->instanceImageProvider()->setModelNode(propertyEditor->firstSelectedModelNode());
|
|
||||||
updateInstanceImage();
|
|
||||||
|
|
||||||
qCInfo(propertyEditorBenchmark) << "final:" << time.elapsed();
|
|
||||||
} else {
|
|
||||||
qWarning() << "PropertyEditor: invalid node for setup";
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
contextObject()->setMajorQtQuickVersion(qmlObjectNode.view()->majorQtQuickVersion());
|
||||||
|
contextObject()->setMinorQtQuickVersion(qmlObjectNode.view()->minorQtQuickVersion());
|
||||||
|
|
||||||
|
contextObject()->setHasMaterialLibrary(Utils3D::materialLibraryNode(propertyEditor).isValid());
|
||||||
|
contextObject()->setIsQt6Project(propertyEditor->externalDependencies().isQt6Project());
|
||||||
|
contextObject()->setEditorNodes(editorNodes);
|
||||||
|
contextObject()->setHasQuick3DImport(propertyEditor->model()->hasImport("QtQuick3D"));
|
||||||
|
|
||||||
|
m_view->instanceImageProvider()->setModelNode(m_backendModelNode.singleSelectedNode());
|
||||||
|
updateInstanceImage();
|
||||||
|
|
||||||
|
qCInfo(propertyEditorBenchmark) << "final:" << time.elapsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PropertyEditorQmlBackend::propertyEditorResourcesPath()
|
QString PropertyEditorQmlBackend::propertyEditorResourcesPath()
|
||||||
@@ -960,35 +965,6 @@ QString PropertyEditorQmlBackend::resourcesPath(const QString &dir)
|
|||||||
return Core::ICore::resourcePath("qmldesigner/" + dir).toUrlishString();
|
return Core::ICore::resourcePath("qmldesigner/" + dir).toUrlishString();
|
||||||
}
|
}
|
||||||
|
|
||||||
static NodeMetaInfo findCommonSuperClass(const NodeMetaInfo &first, const NodeMetaInfo &second)
|
|
||||||
{
|
|
||||||
auto commonBase = first.commonBase(second);
|
|
||||||
|
|
||||||
return commonBase.isValid() ? commonBase : first;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeMetaInfo PropertyEditorQmlBackend::findCommonAncestor(const ModelNode &node)
|
|
||||||
{
|
|
||||||
if (!node.isValid())
|
|
||||||
return node.metaInfo();
|
|
||||||
|
|
||||||
AbstractView *view = node.view();
|
|
||||||
|
|
||||||
const QList<ModelNode> &selectedNodes = view->selectedModelNodes();
|
|
||||||
if (selectedNodes.size() > 1) {
|
|
||||||
NodeMetaInfo commonClass = node.metaInfo();
|
|
||||||
|
|
||||||
for (const ModelNode &selectedNode : selectedNodes) {
|
|
||||||
const NodeMetaInfo &nodeMetaInfo = selectedNode.metaInfo();
|
|
||||||
if (nodeMetaInfo.isValid() && !nodeMetaInfo.isBasedOn(commonClass))
|
|
||||||
commonClass = findCommonSuperClass(nodeMetaInfo, commonClass);
|
|
||||||
}
|
|
||||||
return commonClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node.metaInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyEditorQmlBackend::refreshBackendModel()
|
void PropertyEditorQmlBackend::refreshBackendModel()
|
||||||
{
|
{
|
||||||
m_backendModelNode.refresh();
|
m_backendModelNode.refresh();
|
||||||
@@ -1064,7 +1040,6 @@ bool PropertyEditorQmlBackend::checkIfUrlExists(const QUrl &url)
|
|||||||
void PropertyEditorQmlBackend::emitSelectionToBeChanged()
|
void PropertyEditorQmlBackend::emitSelectionToBeChanged()
|
||||||
{
|
{
|
||||||
m_backendModelNode.emitSelectionToBeChanged();
|
m_backendModelNode.emitSelectionToBeChanged();
|
||||||
m_backendTextureNode.updateSelectionDetails();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyEditorQmlBackend::emitSelectionChanged()
|
void PropertyEditorQmlBackend::emitSelectionChanged()
|
||||||
|
@@ -40,7 +40,10 @@ public:
|
|||||||
class AsynchronousImageCache &imageCache);
|
class AsynchronousImageCache &imageCache);
|
||||||
~PropertyEditorQmlBackend();
|
~PropertyEditorQmlBackend();
|
||||||
|
|
||||||
void setup(const QmlObjectNode &fxObjectNode, const QString &stateName, const QUrl &qmlSpecificsFile, PropertyEditorView *propertyEditor);
|
void setup(const ModelNodes &editorNodes,
|
||||||
|
const QString &stateName,
|
||||||
|
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);
|
||||||
|
|
||||||
@@ -94,8 +97,7 @@ public:
|
|||||||
void handleModelNodePreviewPixmapChanged(const ModelNode &node,
|
void handleModelNodePreviewPixmapChanged(const ModelNode &node,
|
||||||
const QPixmap &pixmap,
|
const QPixmap &pixmap,
|
||||||
const QByteArray &requestId);
|
const QByteArray &requestId);
|
||||||
|
void handleModelSelectedNodesChanged(PropertyEditorView *propertyEditor);
|
||||||
static NodeMetaInfo findCommonAncestor(const ModelNode &node);
|
|
||||||
|
|
||||||
void refreshBackendModel();
|
void refreshBackendModel();
|
||||||
void refreshPreview();
|
void refreshPreview();
|
||||||
|
@@ -61,6 +61,13 @@ static bool propertyIsAttachedInsightProperty(PropertyNameView propertyName)
|
|||||||
return propertyName.contains("InsightCategory.");
|
return propertyName.contains("InsightCategory.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NodeMetaInfo findCommonSuperClass(const NodeMetaInfo &first, const NodeMetaInfo &second)
|
||||||
|
{
|
||||||
|
auto commonBase = first.commonBase(second);
|
||||||
|
|
||||||
|
return commonBase.isValid() ? commonBase : first;
|
||||||
|
}
|
||||||
|
|
||||||
PropertyEditorView::PropertyEditorView(AsynchronousImageCache &imageCache,
|
PropertyEditorView::PropertyEditorView(AsynchronousImageCache &imageCache,
|
||||||
ExternalDependenciesInterface &externalDependencies)
|
ExternalDependenciesInterface &externalDependencies)
|
||||||
: AbstractView(externalDependencies)
|
: AbstractView(externalDependencies)
|
||||||
@@ -428,6 +435,26 @@ PropertyEditorView *PropertyEditorView::instance()
|
|||||||
return s_instance;
|
return s_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeMetaInfo PropertyEditorView::findCommonAncestor(const ModelNode &node)
|
||||||
|
{
|
||||||
|
if (!node.isValid())
|
||||||
|
return node.metaInfo();
|
||||||
|
|
||||||
|
const QList<ModelNode> allNodes = currentNodes();
|
||||||
|
if (allNodes.size() > 1) {
|
||||||
|
NodeMetaInfo commonClass = node.metaInfo();
|
||||||
|
|
||||||
|
for (const ModelNode &selectedNode : allNodes) {
|
||||||
|
const NodeMetaInfo &nodeMetaInfo = selectedNode.metaInfo();
|
||||||
|
if (nodeMetaInfo.isValid() && !nodeMetaInfo.isBasedOn(commonClass))
|
||||||
|
commonClass = findCommonSuperClass(nodeMetaInfo, commonClass);
|
||||||
|
}
|
||||||
|
return commonClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node.metaInfo();
|
||||||
|
}
|
||||||
|
|
||||||
void PropertyEditorView::updateSize()
|
void PropertyEditorView::updateSize()
|
||||||
{
|
{
|
||||||
if (!m_qmlBackEndForCurrentType)
|
if (!m_qmlBackEndForCurrentType)
|
||||||
@@ -542,7 +569,7 @@ PropertyEditorQmlBackend *getQmlBackend(QHash<QString, PropertyEditorQmlBackend
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setupCurrentQmlBackend(PropertyEditorQmlBackend *currentQmlBackend,
|
void setupCurrentQmlBackend(PropertyEditorQmlBackend *currentQmlBackend,
|
||||||
const ModelNode &selectedNode,
|
const ModelNodes &editorNodes,
|
||||||
const QUrl &qmlSpecificsFile,
|
const QUrl &qmlSpecificsFile,
|
||||||
const QmlModelState ¤tState,
|
const QmlModelState ¤tState,
|
||||||
PropertyEditorView *propertyEditorView,
|
PropertyEditorView *propertyEditorView,
|
||||||
@@ -551,10 +578,9 @@ void setupCurrentQmlBackend(PropertyEditorQmlBackend *currentQmlBackend,
|
|||||||
QString currentStateName = currentState.isBaseState() ? QStringLiteral("invalid state")
|
QString currentStateName = currentState.isBaseState() ? QStringLiteral("invalid state")
|
||||||
: currentState.name();
|
: currentState.name();
|
||||||
|
|
||||||
QmlObjectNode qmlObjectNode{selectedNode};
|
|
||||||
if (specificQmlData.isEmpty())
|
if (specificQmlData.isEmpty())
|
||||||
currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData);
|
currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData);
|
||||||
currentQmlBackend->setup(qmlObjectNode, currentStateName, qmlSpecificsFile, propertyEditorView);
|
currentQmlBackend->setup(editorNodes, currentStateName, qmlSpecificsFile, propertyEditorView);
|
||||||
currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData);
|
currentQmlBackend->contextObject()->setSpecificQmlData(specificQmlData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,7 +660,7 @@ void PropertyEditorView::handleToolBarAction(int action)
|
|||||||
void PropertyEditorView::setupQmlBackend()
|
void PropertyEditorView::setupQmlBackend()
|
||||||
{
|
{
|
||||||
#ifdef QDS_USE_PROJECTSTORAGE
|
#ifdef QDS_USE_PROJECTSTORAGE
|
||||||
const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(activeNode());
|
const NodeMetaInfo commonAncestor = findCommonAncestor(activeNode());
|
||||||
auto selfAndPrototypes = commonAncestor.selfAndPrototypes();
|
auto selfAndPrototypes = commonAncestor.selfAndPrototypes();
|
||||||
bool isEditableComponent = activeNode().isComponent()
|
bool isEditableComponent = activeNode().isComponent()
|
||||||
&& !QmlItemNode(activeNode()).isEffectItem();
|
&& !QmlItemNode(activeNode()).isEffectItem();
|
||||||
@@ -648,7 +674,7 @@ void PropertyEditorView::setupQmlBackend()
|
|||||||
m_stackedWidget,
|
m_stackedWidget,
|
||||||
this);
|
this);
|
||||||
setupCurrentQmlBackend(currentQmlBackend,
|
setupCurrentQmlBackend(currentQmlBackend,
|
||||||
activeNode(),
|
currentNodes(),
|
||||||
QUrl::fromLocalFile(QString{specificsPath}),
|
QUrl::fromLocalFile(QString{specificsPath}),
|
||||||
currentStateNode(),
|
currentStateNode(),
|
||||||
this,
|
this,
|
||||||
@@ -660,7 +686,7 @@ void PropertyEditorView::setupQmlBackend()
|
|||||||
|
|
||||||
setupInsight(rootModelNode(), currentQmlBackend);
|
setupInsight(rootModelNode(), currentQmlBackend);
|
||||||
#else
|
#else
|
||||||
const NodeMetaInfo commonAncestor = PropertyEditorQmlBackend::findCommonAncestor(activeNode());
|
const NodeMetaInfo commonAncestor = findCommonAncestor(activeNode());
|
||||||
|
|
||||||
// qmlFileUrl is panel url. and specifics is its metainfo
|
// qmlFileUrl is panel url. and specifics is its metainfo
|
||||||
const auto [qmlFileUrl, specificsClassMetaInfo] = PropertyEditorQmlBackend::getQmlUrlForMetaInfo(
|
const auto [qmlFileUrl, specificsClassMetaInfo] = PropertyEditorQmlBackend::getQmlUrlForMetaInfo(
|
||||||
@@ -681,7 +707,7 @@ void PropertyEditorView::setupQmlBackend()
|
|||||||
this);
|
this);
|
||||||
|
|
||||||
setupCurrentQmlBackend(currentQmlBackend,
|
setupCurrentQmlBackend(currentQmlBackend,
|
||||||
activeNode(),
|
currentNodes(),
|
||||||
qmlSpecificsFile,
|
qmlSpecificsFile,
|
||||||
currentStateNode(),
|
currentStateNode(),
|
||||||
this,
|
this,
|
||||||
@@ -788,10 +814,12 @@ QList<ModelNode> PropertyEditorView::currentNodes() const
|
|||||||
void PropertyEditorView::selectedNodesChanged(const QList<ModelNode> &,
|
void PropertyEditorView::selectedNodesChanged(const QList<ModelNode> &,
|
||||||
const QList<ModelNode> &)
|
const QList<ModelNode> &)
|
||||||
{
|
{
|
||||||
if (m_isSelectionLocked)
|
if (!m_isSelectionLocked)
|
||||||
return;
|
select();
|
||||||
|
|
||||||
select();
|
// Notify model selection changes to backend regardless of being locked
|
||||||
|
if (m_qmlBackEndForCurrentType)
|
||||||
|
m_qmlBackEndForCurrentType->handleModelSelectedNodesChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PropertyEditorView::isNodeOrChildSelected(const ModelNode &node) const
|
bool PropertyEditorView::isNodeOrChildSelected(const ModelNode &node) const
|
||||||
|
@@ -143,6 +143,8 @@ private: //functions
|
|||||||
|
|
||||||
static PropertyEditorView *instance();
|
static PropertyEditorView *instance();
|
||||||
|
|
||||||
|
NodeMetaInfo findCommonAncestor(const ModelNode &node);
|
||||||
|
|
||||||
private: //variables
|
private: //variables
|
||||||
AsynchronousImageCache &m_imageCache;
|
AsynchronousImageCache &m_imageCache;
|
||||||
ModelNode m_activeNode;
|
ModelNode m_activeNode;
|
||||||
|
@@ -41,11 +41,13 @@ QmlMaterialNodeProxy::QmlMaterialNodeProxy()
|
|||||||
|
|
||||||
QmlMaterialNodeProxy::~QmlMaterialNodeProxy() = default;
|
QmlMaterialNodeProxy::~QmlMaterialNodeProxy() = default;
|
||||||
|
|
||||||
void QmlMaterialNodeProxy::setup(const QmlObjectNode &objectNode)
|
void QmlMaterialNodeProxy::setup(const ModelNodes &editorNodes)
|
||||||
{
|
{
|
||||||
|
QmlObjectNode objectNode = editorNodes.isEmpty() ? ModelNode{} : editorNodes.first();
|
||||||
const QmlObjectNode material = objectNode.metaInfo().isQtQuick3DMaterial() ? objectNode
|
const QmlObjectNode material = objectNode.metaInfo().isQtQuick3DMaterial() ? objectNode
|
||||||
: QmlObjectNode{};
|
: QmlObjectNode{};
|
||||||
setMaterialNode(material);
|
setMaterialNode(material);
|
||||||
|
setEditorNodes(editorNodes);
|
||||||
updatePossibleTypes();
|
updatePossibleTypes();
|
||||||
updatePreviewModel();
|
updatePreviewModel();
|
||||||
}
|
}
|
||||||
@@ -55,6 +57,11 @@ ModelNode QmlMaterialNodeProxy::materialNode() const
|
|||||||
return m_materialNode;
|
return m_materialNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModelNodes QmlMaterialNodeProxy::editorNodes() const
|
||||||
|
{
|
||||||
|
return m_editorNodes;
|
||||||
|
}
|
||||||
|
|
||||||
void QmlMaterialNodeProxy::setPossibleTypes(const QStringList &types)
|
void QmlMaterialNodeProxy::setPossibleTypes(const QStringList &types)
|
||||||
{
|
{
|
||||||
if (types == m_possibleTypes)
|
if (types == m_possibleTypes)
|
||||||
@@ -81,7 +88,7 @@ void QmlMaterialNodeProxy::updatePossibleTypes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
const QString &matType = materialNode().simplifiedTypeName();
|
const QString &matType = materialNode().simplifiedTypeName();
|
||||||
const ModelNodes selectedNodes = materialView()->selectedModelNodes(); // TODO: replace it by PropertyEditorView::currentNodes()
|
const ModelNodes selectedNodes = editorNodes();
|
||||||
bool allAreBasic = Utils::allOf(selectedNodes, [&](const ModelNode &node) {
|
bool allAreBasic = Utils::allOf(selectedNodes, [&](const ModelNode &node) {
|
||||||
return basicTypes.contains(node.simplifiedTypeName());
|
return basicTypes.contains(node.simplifiedTypeName());
|
||||||
});
|
});
|
||||||
@@ -275,6 +282,11 @@ void QmlMaterialNodeProxy::setMaterialNode(const QmlObjectNode &material)
|
|||||||
emit materialNodeChanged();
|
emit materialNodeChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlMaterialNodeProxy::setEditorNodes(const ModelNodes &editorNodes)
|
||||||
|
{
|
||||||
|
m_editorNodes = editorNodes;
|
||||||
|
}
|
||||||
|
|
||||||
bool QmlMaterialNodeProxy::hasQuick3DImport() const
|
bool QmlMaterialNodeProxy::hasQuick3DImport() const
|
||||||
{
|
{
|
||||||
return materialNode().isValid() && materialNode().model()->hasImport("QtQuick3D"_L1);
|
return materialNode().isValid() && materialNode().model()->hasImport("QtQuick3D"_L1);
|
||||||
|
@@ -35,11 +35,12 @@ public:
|
|||||||
explicit QmlMaterialNodeProxy();
|
explicit QmlMaterialNodeProxy();
|
||||||
~QmlMaterialNodeProxy() override;
|
~QmlMaterialNodeProxy() override;
|
||||||
|
|
||||||
void setup(const QmlObjectNode &objectNode);
|
void setup(const ModelNodes &editorNodes);
|
||||||
|
|
||||||
QStringList possibleTypes() const { return m_possibleTypes; }
|
QStringList possibleTypes() const { return m_possibleTypes; }
|
||||||
|
|
||||||
ModelNode materialNode() const;
|
ModelNode materialNode() const;
|
||||||
|
ModelNodes editorNodes() const;
|
||||||
|
|
||||||
int possibleTypeIndex() const { return m_possibleTypeIndex; }
|
int possibleTypeIndex() const { return m_possibleTypeIndex; }
|
||||||
|
|
||||||
@@ -67,15 +68,15 @@ private: // Methods
|
|||||||
void updatePossibleTypeIndex();
|
void updatePossibleTypeIndex();
|
||||||
void updatePreviewModel();
|
void updatePreviewModel();
|
||||||
void setMaterialNode(const QmlObjectNode &material);
|
void setMaterialNode(const QmlObjectNode &material);
|
||||||
|
void setEditorNodes(const ModelNodes &editorNodes);
|
||||||
|
|
||||||
bool hasQuick3DImport() const;
|
bool hasQuick3DImport() const;
|
||||||
|
|
||||||
AbstractView *materialView() const;
|
AbstractView *materialView() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_has3DModelSelection = false;
|
|
||||||
|
|
||||||
QmlObjectNode m_materialNode;
|
QmlObjectNode m_materialNode;
|
||||||
|
ModelNodes m_editorNodes;
|
||||||
|
|
||||||
QStringList m_possibleTypes;
|
QStringList m_possibleTypes;
|
||||||
int m_possibleTypeIndex = -1;
|
int m_possibleTypeIndex = -1;
|
||||||
|
@@ -22,9 +22,15 @@ QmlModelNodeProxy::QmlModelNodeProxy(QObject *parent) :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlModelNodeProxy::setup(const QmlObjectNode &objectNode)
|
void QmlModelNodeProxy::setup(const ModelNode &node)
|
||||||
{
|
{
|
||||||
m_qmlObjectNode = objectNode;
|
setup(ModelNodes{node});
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlModelNodeProxy::setup(const ModelNodes &editorNodes)
|
||||||
|
{
|
||||||
|
m_qmlObjectNode = editorNodes.isEmpty() ? ModelNode{} : editorNodes.first();
|
||||||
|
m_editorNodes = editorNodes;
|
||||||
|
|
||||||
m_subselection.clear();
|
m_subselection.clear();
|
||||||
|
|
||||||
@@ -61,12 +67,22 @@ ModelNode QmlModelNodeProxy::modelNode() const
|
|||||||
return m_qmlObjectNode.modelNode();
|
return m_qmlObjectNode.modelNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModelNodes QmlModelNodeProxy::editorNodes() const
|
||||||
|
{
|
||||||
|
return m_editorNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelNode QmlModelNodeProxy::singleSelectedNode() const
|
||||||
|
{
|
||||||
|
return multiSelection() ? ModelNode{} : modelNode();
|
||||||
|
}
|
||||||
|
|
||||||
bool QmlModelNodeProxy::multiSelection() const
|
bool QmlModelNodeProxy::multiSelection() const
|
||||||
{
|
{
|
||||||
if (!m_qmlObjectNode.isValid())
|
if (!m_qmlObjectNode.isValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return m_qmlObjectNode.view()->selectedModelNodes().size() > 1;
|
return editorNodes().size() > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlModelNodeProxy::nodeId() const
|
QString QmlModelNodeProxy::nodeId() const
|
||||||
|
@@ -22,7 +22,8 @@ class QMLDESIGNER_EXPORT QmlModelNodeProxy : public QObject
|
|||||||
public:
|
public:
|
||||||
explicit QmlModelNodeProxy(QObject *parent = nullptr);
|
explicit QmlModelNodeProxy(QObject *parent = nullptr);
|
||||||
|
|
||||||
void setup(const QmlObjectNode &objectNode);
|
void setup(const ModelNode &node);
|
||||||
|
void setup(const ModelNodes &editorNodes);
|
||||||
|
|
||||||
static void registerDeclarativeType();
|
static void registerDeclarativeType();
|
||||||
|
|
||||||
@@ -33,6 +34,8 @@ public:
|
|||||||
QmlObjectNode qmlObjectNode() const;
|
QmlObjectNode qmlObjectNode() const;
|
||||||
|
|
||||||
ModelNode modelNode() const;
|
ModelNode modelNode() const;
|
||||||
|
ModelNodes editorNodes() const;
|
||||||
|
ModelNode singleSelectedNode() const;
|
||||||
|
|
||||||
bool multiSelection() const;
|
bool multiSelection() const;
|
||||||
|
|
||||||
@@ -81,6 +84,7 @@ private:
|
|||||||
PropertyEditorSubSelectionWrapper *findWrapper(int internalId) const;
|
PropertyEditorSubSelectionWrapper *findWrapper(int internalId) const;
|
||||||
|
|
||||||
QmlObjectNode m_qmlObjectNode;
|
QmlObjectNode m_qmlObjectNode;
|
||||||
|
ModelNodes m_editorNodes;
|
||||||
QList<QSharedPointer<PropertyEditorSubSelectionWrapper>> m_subselection;
|
QList<QSharedPointer<PropertyEditorSubSelectionWrapper>> m_subselection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -211,7 +211,7 @@ void TextureEditorQmlBackend::setup(const QmlObjectNode &selectedTextureNode, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// model node
|
// model node
|
||||||
m_backendModelNode.setup(selectedTextureNode.modelNode());
|
m_backendModelNode.setup(selectedTextureNode);
|
||||||
context()->setContextProperty("modelNodeBackend", &m_backendModelNode);
|
context()->setContextProperty("modelNodeBackend", &m_backendModelNode);
|
||||||
context()->setContextProperty("hasTexture", QVariant(true));
|
context()->setContextProperty("hasTexture", QVariant(true));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user