From 8a8b8c46025752175edf7d894613eeb33188b005 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Fri, 2 Mar 2018 15:29:26 +0100 Subject: [PATCH] QmlDesigner: Add meta hint if item renders children directly In some cases items render their children directly using an effect. In this case we do not want to hide the children when calling refFromEffectItem(). If the hint takesOverRenderingOfChildren is set in the .metainfo hints for a parent item we forward a flag to the puppet and refFromEffectItem() is not hiding this item, Change-Id: I37a8c0ad8a15bc914c220e03b1b744779431d655 Reviewed-by: Alessandro Portale --- .../qmlpuppet/container/instancecontainer.cpp | 33 +++++++++++-- .../qmlpuppet/container/instancecontainer.h | 20 +++++++- .../instances/objectnodeinstance.cpp | 3 +- .../qml2puppet/instances/objectnodeinstance.h | 4 +- .../instances/quickitemnodeinstance.cpp | 8 ++-- .../instances/quickitemnodeinstance.h | 3 +- .../instances/servernodeinstance.cpp | 6 ++- .../designercore/include/nodehints.h | 1 + .../instances/nodeinstanceview.cpp | 46 ++++++++++++++++--- .../designercore/metainfo/nodehints.cpp | 12 ++++- 10 files changed, 116 insertions(+), 20 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/container/instancecontainer.cpp b/share/qtcreator/qml/qmlpuppet/container/instancecontainer.cpp index bb9ec181610..6e480ceef98 100644 --- a/share/qtcreator/qml/qmlpuppet/container/instancecontainer.cpp +++ b/share/qtcreator/qml/qmlpuppet/container/instancecontainer.cpp @@ -44,9 +44,24 @@ InstanceContainer::InstanceContainer() { } -InstanceContainer::InstanceContainer(qint32 instanceId, const TypeName &type, int majorNumber, int minorNumber, const QString &componentPath, const QString &nodeSource, NodeSourceType nodeSourceType, NodeMetaType metaType) - : m_instanceId(instanceId), m_type(properDelemitingOfType(type)), m_majorNumber(majorNumber), m_minorNumber(minorNumber), m_componentPath(componentPath), - m_nodeSource(nodeSource), m_nodeSourceType(nodeSourceType), m_metaType(metaType) +InstanceContainer::InstanceContainer(qint32 instanceId, + const TypeName &type, + int majorNumber, + int minorNumber, + const QString &componentPath, + const QString &nodeSource, + NodeSourceType nodeSourceType, + NodeMetaType metaType, + NodeFlags metaFlags) + : m_instanceId(instanceId) + ,m_type(properDelemitingOfType(type)) + ,m_majorNumber(majorNumber) + ,m_minorNumber(minorNumber) + ,m_componentPath(componentPath) + ,m_nodeSource(nodeSource) + ,m_nodeSourceType(nodeSourceType) + ,m_metaType(metaType) + ,m_metaFlags(metaFlags) { } @@ -90,6 +105,16 @@ InstanceContainer::NodeMetaType InstanceContainer::metaType() const return static_cast(m_metaType); } +InstanceContainer::NodeFlags InstanceContainer::metaFlags() const +{ + return m_metaFlags; +} + +bool InstanceContainer::checkFlag(NodeFlag flag) const +{ + return NodeFlags(m_metaFlags).testFlag(flag); +} + QDataStream &operator<<(QDataStream &out, const InstanceContainer &container) { out << container.instanceId(); @@ -100,6 +125,7 @@ QDataStream &operator<<(QDataStream &out, const InstanceContainer &container) out << container.nodeSource(); out << qint32(container.nodeSourceType()); out << qint32(container.metaType()); + out << qint32(container.metaFlags()); return out; } @@ -115,6 +141,7 @@ QDataStream &operator>>(QDataStream &in, InstanceContainer &container) in >> container.m_nodeSource; in >> container.m_nodeSourceType; in >> container.m_metaType; + in >> container.m_metaFlags; return in; } diff --git a/share/qtcreator/qml/qmlpuppet/container/instancecontainer.h b/share/qtcreator/qml/qmlpuppet/container/instancecontainer.h index 6dc86bf93c9..9d4c21b1274 100644 --- a/share/qtcreator/qml/qmlpuppet/container/instancecontainer.h +++ b/share/qtcreator/qml/qmlpuppet/container/instancecontainer.h @@ -54,8 +54,22 @@ public: ItemMetaType }; + enum NodeFlag { + ParentTakesOverRendering = 1 + }; + + Q_DECLARE_FLAGS(NodeFlags, NodeFlag) + InstanceContainer(); - InstanceContainer(qint32 instanceId, const TypeName &type, int majorNumber, int minorNumber, const QString &componentPath, const QString &nodeSource, NodeSourceType nodeSourceType, NodeMetaType metaType); + InstanceContainer(qint32 instanceId, + const TypeName &type, + int majorNumber, + int minorNumber, + const QString &componentPath, + const QString &nodeSource, + NodeSourceType nodeSourceType, + NodeMetaType metaType, + NodeFlags metaFlags); qint32 instanceId() const; TypeName type() const; @@ -65,6 +79,8 @@ public: QString nodeSource() const; NodeSourceType nodeSourceType() const; NodeMetaType metaType() const; + bool checkFlag(NodeFlag flag) const; + NodeFlags metaFlags() const; private: qint32 m_instanceId = -1; @@ -75,6 +91,7 @@ private: QString m_nodeSource; qint32 m_nodeSourceType = 0; qint32 m_metaType = 0; + qint32 m_metaFlags = 0; }; QDebug operator <<(QDebug debug, const InstanceContainer &command); @@ -82,3 +99,4 @@ QDebug operator <<(QDebug debug, const InstanceContainer &command); } // namespace QmlDesigner Q_DECLARE_METATYPE(QmlDesigner::InstanceContainer) +Q_DECLARE_OPERATORS_FOR_FLAGS(QmlDesigner::InstanceContainer::NodeFlags) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp index 1dc4716649c..3ee177a3872 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp @@ -126,7 +126,8 @@ void ObjectNodeInstance::initializePropertyWatcher(const ObjectNodeInstance::Poi m_signalSpy.setObjectNodeInstance(objectNodeInstance); } -void ObjectNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance) +void ObjectNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, + InstanceContainer::NodeFlags /*flags*/) { initializePropertyWatcher(objectNodeInstance); QmlPrivateGate::registerNodeInstanceMetaObject(objectNodeInstance->object(), objectNodeInstance->nodeInstanceServer()->engine()); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h index 8266f0addf8..5977d3d31ce 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.h @@ -28,6 +28,8 @@ #include "nodeinstanceserver.h" #include "nodeinstancesignalspy.h" +#include "instancecontainer.h" + #include #include #include @@ -78,7 +80,7 @@ public: NodeInstanceServer *nodeInstanceServer() const; void setNodeInstanceServer(NodeInstanceServer *server); - virtual void initialize(const Pointer &objectNodeInstance); + virtual void initialize(const Pointer &objectNodeInstance, InstanceContainer::NodeFlags flags); virtual QImage renderImage() const; virtual QImage renderPreviewImage(const QSize &previewImageSize) const; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp index a30fbc184a9..647d1d74706 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.cpp @@ -156,7 +156,8 @@ void QuickItemNodeInstance::createEffectItem(bool createEffectItem) s_createEffectItem = createEffectItem; } -void QuickItemNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance) +void QuickItemNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, + InstanceContainer::NodeFlags flags) { if (instanceId() == 0) { @@ -167,10 +168,11 @@ void QuickItemNodeInstance::initialize(const ObjectNodeInstance::Pointer &object if (quickItem()->window()) { if (s_createEffectItem || instanceId() == 0) - designerSupport()->refFromEffectItem(quickItem()); + designerSupport()->refFromEffectItem(quickItem(), + !flags.testFlag(InstanceContainer::ParentTakesOverRendering)); } - ObjectNodeInstance::initialize(objectNodeInstance); + ObjectNodeInstance::initialize(objectNodeInstance, flags); quickItem()->update(); } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.h index d655a9a1032..1f000f1ba2b 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quickitemnodeinstance.h @@ -46,7 +46,8 @@ public: static Pointer create(QObject *objectToBeWrapped); static void createEffectItem(bool createEffectItem); - void initialize(const ObjectNodeInstance::Pointer &objectNodeInstance) override; + void initialize(const ObjectNodeInstance::Pointer &objectNodeInstance, + InstanceContainer::NodeFlags flags) override; QQuickItem *contentItem() const override; bool hasContent() const override; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp index 58b17e2451e..2f090517dc8 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp @@ -188,7 +188,9 @@ Internal::ObjectNodeInstance::Pointer ServerNodeInstance::createInstance(QObject return instance; } -ServerNodeInstance ServerNodeInstance::create(NodeInstanceServer *nodeInstanceServer, const InstanceContainer &instanceContainer, ComponentWrap componentWrap) +ServerNodeInstance ServerNodeInstance::create(NodeInstanceServer *nodeInstanceServer, + const InstanceContainer &instanceContainer, + ComponentWrap componentWrap) { Q_ASSERT(instanceContainer.instanceId() != -1); Q_ASSERT(nodeInstanceServer); @@ -229,7 +231,7 @@ ServerNodeInstance ServerNodeInstance::create(NodeInstanceServer *nodeInstanceSe instance.internalInstance()->setInstanceId(instanceContainer.instanceId()); - instance.internalInstance()->initialize(instance.m_nodeInstance); + instance.internalInstance()->initialize(instance.m_nodeInstance, instanceContainer.metaFlags()); return instance; } diff --git a/src/plugins/qmldesigner/designercore/include/nodehints.h b/src/plugins/qmldesigner/designercore/include/nodehints.h index 3fbb89c72cc..982c3a80b06 100644 --- a/src/plugins/qmldesigner/designercore/include/nodehints.h +++ b/src/plugins/qmldesigner/designercore/include/nodehints.h @@ -64,6 +64,7 @@ public: bool isStackedContainer() const; bool canBeReparentedTo(const ModelNode &potenialParent); QString indexPropertyForStackedContainer() const; + bool takesOverRenderingOfChildren() const; QHash hints() const; static NodeHints fromModelNode(const ModelNode &modelNode); diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index 823f966d8c0..e1d07e65afc 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include "abstractproperty.h" @@ -125,7 +126,7 @@ NodeInstanceView::~NodeInstanceView() //\{ -bool isSkippedRootNode(const ModelNode &node) +bool static isSkippedRootNode(const ModelNode &node) { static const PropertyNameList skipList({"Qt.ListModel", "QtQuick.ListModel", "Qt.ListModel", "QtQuick.ListModel"}); @@ -136,7 +137,7 @@ bool isSkippedRootNode(const ModelNode &node) } -bool isSkippedNode(const ModelNode &node) +bool static isSkippedNode(const ModelNode &node) { static const PropertyNameList skipList({"QtQuick.XmlRole", "Qt.XmlRole", "QtQuick.ListElement", "Qt.ListElement"}); @@ -146,6 +147,22 @@ bool isSkippedNode(const ModelNode &node) return false; } +bool static parentTakesOverRendering(const ModelNode &modelNode) +{ + if (!modelNode.isValid()) + return false; + + ModelNode currentNode = modelNode; + + while (currentNode.hasParentProperty()) { + currentNode = currentNode.parentProperty().parentModelNode(); + if (NodeHints::fromModelNode(currentNode).takesOverRenderingOfChildren()) + return true; + } + + return false; +} + /*! Notifies the view that it was attached to \a model. For every model node in the model, a NodeInstance will be created. @@ -817,6 +834,11 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() if (instance.modelNode().metaInfo().isSubclassOf("QtQuick.Item")) nodeMetaType = InstanceContainer::ItemMetaType; + InstanceContainer::NodeFlags nodeFlags; + + if (parentTakesOverRendering(instance.modelNode())) + nodeFlags.setFlag(InstanceContainer::ParentTakesOverRendering); + InstanceContainer container(instance.instanceId(), instance.modelNode().type(), instance.modelNode().majorVersion(), @@ -824,8 +846,8 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() instance.modelNode().metaInfo().componentFileName(), instance.modelNode().nodeSource(), nodeSourceType, - nodeMetaType - ); + nodeMetaType, + nodeFlags); instanceContainerList.append(container); } @@ -958,8 +980,20 @@ CreateInstancesCommand NodeInstanceView::createCreateInstancesCommand(const QLis if (instance.modelNode().metaInfo().isSubclassOf("QtQuick.Item")) nodeMetaType = InstanceContainer::ItemMetaType; - InstanceContainer container(instance.instanceId(), instance.modelNode().type(), instance.modelNode().majorVersion(), instance.modelNode().minorVersion(), - instance.modelNode().metaInfo().componentFileName(), instance.modelNode().nodeSource(), nodeSourceType, nodeMetaType); + InstanceContainer::NodeFlags nodeFlags; + + if (parentTakesOverRendering(instance.modelNode())) + nodeFlags.setFlag(InstanceContainer::ParentTakesOverRendering); + + InstanceContainer container(instance.instanceId(), + instance.modelNode().type(), + instance.modelNode().majorVersion(), + instance.modelNode().minorVersion(), + instance.modelNode().metaInfo().componentFileName(), + instance.modelNode().nodeSource(), + nodeSourceType, + nodeMetaType, + nodeFlags); containerList.append(container); } diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp index 1a38b0a631f..28d7c0a205a 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/nodehints.cpp @@ -193,6 +193,14 @@ QString NodeHints::indexPropertyForStackedContainer() const return Internal::evaluateExpression(expression, modelNode(), ModelNode()).toString(); } +bool NodeHints::takesOverRenderingOfChildren() const +{ + if (!isValid()) + return false; + + return evaluateBooleanExpression("takesOverRenderingOfChildren", false); +} + QHash NodeHints::hints() const { return m_hints; @@ -277,7 +285,7 @@ bool JSObject::potentialParentIsRoot() const bool JSObject::potentialChildIsRoot() const { - return m_otherNode.isValid() && m_otherNode.isRootNode(); + return m_otherNode.isValid() && m_otherNode.isRootNode(); } bool JSObject::isSubclassOf(const QString &typeName) @@ -303,7 +311,7 @@ bool JSObject::rootItemIsSubclassOf(const QString &typeName) bool JSObject::currentParentIsSubclassOf(const QString &typeName) { if (m_modelNode.hasParentProperty() - && m_modelNode.parentProperty().isValid()) { + && m_modelNode.parentProperty().isValid()) { NodeMetaInfo metaInfo = m_modelNode.parentProperty().parentModelNode().metaInfo(); if (metaInfo.isValid()) return metaInfo.isSubclassOf(typeName.toUtf8());