forked from qt-creator/qt-creator
QmlDesigner: Add anchor tracing
Change-Id: Ie687940dbedd820cbfd5deb9323f4bad3cac0ea2 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
static auto category = ModelTracing::category;
|
||||||
|
|
||||||
AnchorLine::AnchorLine()
|
AnchorLine::AnchorLine()
|
||||||
: m_qmlItemNode(QmlItemNode())
|
: m_qmlItemNode(QmlItemNode())
|
||||||
, m_type(AnchorLineInvalid)
|
, m_type(AnchorLineInvalid)
|
||||||
@@ -20,8 +22,11 @@ AnchorLineType AnchorLine::type() const
|
|||||||
return m_type;
|
return m_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AnchorLine::isValid() const
|
bool AnchorLine::isValid(SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"anchor line is valid", category(), keyValue("caller location", sl)};
|
||||||
|
|
||||||
return m_type != AnchorLineInvalid && m_qmlItemNode.isValid();
|
return m_type != AnchorLineInvalid && m_qmlItemNode.isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,11 +11,14 @@ namespace QmlDesigner {
|
|||||||
|
|
||||||
class QMLDESIGNER_EXPORT AnchorLine
|
class QMLDESIGNER_EXPORT AnchorLine
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
using SL = ModelTracing::SourceLocation;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AnchorLine();
|
AnchorLine();
|
||||||
AnchorLine(const QmlItemNode &qmlItemNode, AnchorLineType type);
|
AnchorLine(const QmlItemNode &qmlItemNode, AnchorLineType type);
|
||||||
AnchorLineType type() const;
|
AnchorLineType type() const;
|
||||||
bool isValid() const;
|
bool isValid(SL sl = {}) const;
|
||||||
|
|
||||||
static bool isHorizontalAnchorLine(AnchorLineType anchorline);
|
static bool isHorizontalAnchorLine(AnchorLineType anchorline);
|
||||||
static bool isVerticalAnchorLine(AnchorLineType anchorline);
|
static bool isVerticalAnchorLine(AnchorLineType anchorline);
|
||||||
|
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
static auto category = ModelTracing::category;
|
||||||
|
|
||||||
static PropertyName lineTypeToString(AnchorLineType lineType)
|
static PropertyName lineTypeToString(AnchorLineType lineType)
|
||||||
{
|
{
|
||||||
switch (lineType) {
|
switch (lineType) {
|
||||||
@@ -114,19 +116,28 @@ QmlItemNode QmlAnchors::qmlItemNode() const
|
|||||||
return m_qmlItemNode;
|
return m_qmlItemNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlAnchors::modelHasAnchors() const
|
bool QmlAnchors::modelHasAnchors(SL sl) const
|
||||||
{
|
{
|
||||||
return modelHasAnchor(AnchorLineLeft)
|
using NanotraceHR::keyValue;
|
||||||
|| modelHasAnchor(AnchorLineRight)
|
NanotraceHR::Tracer tracer{"qml anchors has anchors",
|
||||||
|| modelHasAnchor(AnchorLineTop)
|
category(),
|
||||||
|| modelHasAnchor(AnchorLineBottom)
|
keyValue("model node", *this),
|
||||||
|| modelHasAnchor(AnchorLineHorizontalCenter)
|
keyValue("caller location", sl)};
|
||||||
|| modelHasAnchor(AnchorLineVerticalCenter)
|
|
||||||
|| modelHasAnchor(AnchorLineBaseline);
|
return modelHasAnchor(AnchorLineLeft) || modelHasAnchor(AnchorLineRight)
|
||||||
|
|| modelHasAnchor(AnchorLineTop) || modelHasAnchor(AnchorLineBottom)
|
||||||
|
|| modelHasAnchor(AnchorLineHorizontalCenter) || modelHasAnchor(AnchorLineVerticalCenter)
|
||||||
|
|| modelHasAnchor(AnchorLineBaseline);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlAnchors::modelHasAnchor(AnchorLineType sourceAnchorLineType) const
|
bool QmlAnchors::modelHasAnchor(AnchorLineType sourceAnchorLineType, SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors has anchor",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
const PropertyNameView propertyName = anchorPropertyName(sourceAnchorLineType);
|
const PropertyNameView propertyName = anchorPropertyName(sourceAnchorLineType);
|
||||||
|
|
||||||
if (sourceAnchorLineType & AnchorLineFill)
|
if (sourceAnchorLineType & AnchorLineFill)
|
||||||
@@ -138,20 +149,37 @@ bool QmlAnchors::modelHasAnchor(AnchorLineType sourceAnchorLineType) const
|
|||||||
return qmlItemNode().modelNode().hasBindingProperty(anchorPropertyName(sourceAnchorLineType));
|
return qmlItemNode().modelNode().hasBindingProperty(anchorPropertyName(sourceAnchorLineType));
|
||||||
}
|
}
|
||||||
|
|
||||||
AnchorLine QmlAnchors::modelAnchor(AnchorLineType sourceAnchorLineType) const
|
AnchorLine QmlAnchors::modelAnchor(AnchorLineType sourceAnchorLineType, SL sl) const
|
||||||
{
|
{
|
||||||
QPair<PropertyName, ModelNode> targetAnchorLinePair;
|
using NanotraceHR::keyValue;
|
||||||
if (sourceAnchorLineType & AnchorLineFill && qmlItemNode().modelNode().hasBindingProperty("anchors.fill")) {
|
NanotraceHR::Tracer tracer{"qml anchors get anchor",
|
||||||
targetAnchorLinePair.second = qmlItemNode().modelNode().bindingProperty("anchors.fill").resolveToModelNode();
|
category(),
|
||||||
targetAnchorLinePair.first = lineTypeToString(sourceAnchorLineType);
|
keyValue("model node", *this),
|
||||||
} else if (sourceAnchorLineType & AnchorLineCenter && qmlItemNode().modelNode().hasBindingProperty("anchors.centerIn")) {
|
keyValue("caller location", sl)};
|
||||||
targetAnchorLinePair.second = qmlItemNode().modelNode().bindingProperty("anchors.centerIn").resolveToModelNode();
|
|
||||||
targetAnchorLinePair.first = lineTypeToString(sourceAnchorLineType);
|
QPair<PropertyName, ModelNode> targetAnchorLinePair;
|
||||||
} else {
|
if (sourceAnchorLineType & AnchorLineFill
|
||||||
AbstractProperty binding = qmlItemNode().modelNode().bindingProperty(anchorPropertyName(sourceAnchorLineType)).resolveToProperty();
|
&& qmlItemNode().modelNode().hasBindingProperty("anchors.fill")) {
|
||||||
targetAnchorLinePair.first = binding.name().toByteArray();
|
targetAnchorLinePair.second = qmlItemNode()
|
||||||
targetAnchorLinePair.second = binding.parentModelNode();
|
.modelNode()
|
||||||
}
|
.bindingProperty("anchors.fill")
|
||||||
|
.resolveToModelNode();
|
||||||
|
targetAnchorLinePair.first = lineTypeToString(sourceAnchorLineType);
|
||||||
|
} else if (sourceAnchorLineType & AnchorLineCenter
|
||||||
|
&& qmlItemNode().modelNode().hasBindingProperty("anchors.centerIn")) {
|
||||||
|
targetAnchorLinePair.second = qmlItemNode()
|
||||||
|
.modelNode()
|
||||||
|
.bindingProperty("anchors.centerIn")
|
||||||
|
.resolveToModelNode();
|
||||||
|
targetAnchorLinePair.first = lineTypeToString(sourceAnchorLineType);
|
||||||
|
} else {
|
||||||
|
AbstractProperty binding = qmlItemNode()
|
||||||
|
.modelNode()
|
||||||
|
.bindingProperty(anchorPropertyName(sourceAnchorLineType))
|
||||||
|
.resolveToProperty();
|
||||||
|
targetAnchorLinePair.first = binding.name().toByteArray();
|
||||||
|
targetAnchorLinePair.second = binding.parentModelNode();
|
||||||
|
}
|
||||||
|
|
||||||
AnchorLineType targetAnchorLine = propertyNameToLineType(targetAnchorLinePair.first);
|
AnchorLineType targetAnchorLine = propertyNameToLineType(targetAnchorLinePair.first);
|
||||||
|
|
||||||
@@ -162,35 +190,53 @@ AnchorLine QmlAnchors::modelAnchor(AnchorLineType sourceAnchorLineType) const
|
|||||||
return AnchorLine(QmlItemNode(targetAnchorLinePair.second), targetAnchorLine);
|
return AnchorLine(QmlItemNode(targetAnchorLinePair.second), targetAnchorLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlAnchors::isValid() const
|
bool QmlAnchors::isValid(SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors is valid",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
return m_qmlItemNode.isValid();
|
return m_qmlItemNode.isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAnchors::setAnchor(AnchorLineType sourceAnchorLine,
|
void QmlAnchors::setAnchor(AnchorLineType sourceAnchorLine,
|
||||||
const QmlItemNode &targetQmlItemNode,
|
const QmlItemNode &targetQmlItemNode,
|
||||||
AnchorLineType targetAnchorLine)
|
AnchorLineType targetAnchorLine,
|
||||||
|
SL sl)
|
||||||
{
|
{
|
||||||
qmlItemNode().view()->executeInTransaction("QmlAnchors::setAnchor", [this, sourceAnchorLine, targetQmlItemNode, targetAnchorLine](){
|
using NanotraceHR::keyValue;
|
||||||
if (qmlItemNode().isInBaseState()) {
|
NanotraceHR::Tracer tracer{"qml anchors set anchor",
|
||||||
if ((qmlItemNode().nodeInstance().hasAnchor("anchors.fill") && (sourceAnchorLine & AnchorLineFill))
|
category(),
|
||||||
|| ((qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn") && (sourceAnchorLine & AnchorLineCenter)))) {
|
keyValue("model node", *this),
|
||||||
removeAnchor(sourceAnchorLine);
|
keyValue("caller location", sl)};
|
||||||
}
|
|
||||||
|
|
||||||
const PropertyNameView propertyName = anchorPropertyName(sourceAnchorLine);
|
qmlItemNode().view()->executeInTransaction(
|
||||||
ModelNode targetModelNode = targetQmlItemNode.modelNode();
|
"QmlAnchors::setAnchor", [this, sourceAnchorLine, targetQmlItemNode, targetAnchorLine]() {
|
||||||
QString targetExpression = targetModelNode.validId();
|
if (qmlItemNode().isInBaseState()) {
|
||||||
if (targetQmlItemNode.modelNode() == qmlItemNode().modelNode().parentProperty().parentModelNode())
|
if ((qmlItemNode().nodeInstance().hasAnchor("anchors.fill")
|
||||||
targetExpression = QLatin1String("parent");
|
&& (sourceAnchorLine & AnchorLineFill))
|
||||||
if (sourceAnchorLine != AnchorLineCenter && sourceAnchorLine != AnchorLineFill)
|
|| ((qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn")
|
||||||
targetExpression = targetExpression + QLatin1Char('.') + QString::fromLatin1(lineTypeToString(targetAnchorLine));
|
&& (sourceAnchorLine & AnchorLineCenter)))) {
|
||||||
qmlItemNode().modelNode().bindingProperty(propertyName).setExpression(targetExpression);
|
removeAnchor(sourceAnchorLine);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
const PropertyNameView propertyName = anchorPropertyName(sourceAnchorLine);
|
||||||
|
ModelNode targetModelNode = targetQmlItemNode.modelNode();
|
||||||
|
QString targetExpression = targetModelNode.validId();
|
||||||
|
if (targetQmlItemNode.modelNode()
|
||||||
|
== qmlItemNode().modelNode().parentProperty().parentModelNode())
|
||||||
|
targetExpression = QLatin1String("parent");
|
||||||
|
if (sourceAnchorLine != AnchorLineCenter && sourceAnchorLine != AnchorLineFill)
|
||||||
|
targetExpression = targetExpression + QLatin1Char('.')
|
||||||
|
+ QString::fromLatin1(lineTypeToString(targetAnchorLine));
|
||||||
|
qmlItemNode().modelNode().bindingProperty(propertyName).setExpression(targetExpression);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool detectHorizontalCycle(const ModelNode &node, QList<ModelNode> knownNodeList)
|
static bool detectHorizontalCycle(const ModelNode &node, QList<ModelNode> knownNodeList)
|
||||||
{
|
{
|
||||||
if (knownNodeList.contains(node))
|
if (knownNodeList.contains(node))
|
||||||
return true;
|
return true;
|
||||||
@@ -227,7 +273,7 @@ bool detectHorizontalCycle(const ModelNode &node, QList<ModelNode> knownNodeList
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool detectVerticalCycle(const ModelNode &node, QList<ModelNode> knownNodeList)
|
static bool detectVerticalCycle(const ModelNode &node, QList<ModelNode> knownNodeList)
|
||||||
{
|
{
|
||||||
if (!node.isValid())
|
if (!node.isValid())
|
||||||
return false;
|
return false;
|
||||||
@@ -267,8 +313,14 @@ bool detectVerticalCycle(const ModelNode &node, QList<ModelNode> knownNodeList)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlAnchors::canAnchor(const QmlItemNode &targetModelNode) const
|
bool QmlAnchors::canAnchor(const QmlItemNode &targetModelNode, SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors can anchor",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
if (!qmlItemNode().isInBaseState())
|
if (!qmlItemNode().isInBaseState())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -282,8 +334,15 @@ bool QmlAnchors::canAnchor(const QmlItemNode &targetModelNode) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
AnchorLineType QmlAnchors::possibleAnchorLines(AnchorLineType sourceAnchorLineType,
|
AnchorLineType QmlAnchors::possibleAnchorLines(AnchorLineType sourceAnchorLineType,
|
||||||
const QmlItemNode &targetQmlItemNode) const
|
const QmlItemNode &targetQmlItemNode,
|
||||||
|
SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors possible anchor lines",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
if (!canAnchor(targetQmlItemNode))
|
if (!canAnchor(targetQmlItemNode))
|
||||||
return AnchorLineInvalid;
|
return AnchorLineInvalid;
|
||||||
|
|
||||||
@@ -300,8 +359,14 @@ AnchorLineType QmlAnchors::possibleAnchorLines(AnchorLineType sourceAnchorLineTy
|
|||||||
return AnchorLineInvalid;
|
return AnchorLineInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnchorLine QmlAnchors::instanceAnchor(AnchorLineType sourceAnchorLine) const
|
AnchorLine QmlAnchors::instanceAnchor(AnchorLineType sourceAnchorLine, SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors get instance anchor",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
QPair<PropertyName, qint32> targetAnchorLinePair;
|
QPair<PropertyName, qint32> targetAnchorLinePair;
|
||||||
if (qmlItemNode().nodeInstance().hasAnchor("anchors.fill") && (sourceAnchorLine & AnchorLineFill)) {
|
if (qmlItemNode().nodeInstance().hasAnchor("anchors.fill") && (sourceAnchorLine & AnchorLineFill)) {
|
||||||
targetAnchorLinePair = qmlItemNode().nodeInstance().anchor("anchors.fill");
|
targetAnchorLinePair = qmlItemNode().nodeInstance().anchor("anchors.fill");
|
||||||
@@ -324,9 +389,15 @@ AnchorLine QmlAnchors::instanceAnchor(AnchorLineType sourceAnchorLine) const
|
|||||||
return AnchorLine(QmlItemNode(qmlItemNode().nodeForInstance(qmlItemNode().nodeInstanceView()->instanceForId(targetAnchorLinePair.second))), targetAnchorLine);
|
return AnchorLine(QmlItemNode(qmlItemNode().nodeForInstance(qmlItemNode().nodeInstanceView()->instanceForId(targetAnchorLinePair.second))), targetAnchorLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAnchors::removeAnchor(AnchorLineType sourceAnchorLine)
|
void QmlAnchors::removeAnchor(AnchorLineType sourceAnchorLine, SL sl)
|
||||||
{
|
{
|
||||||
qmlItemNode().view()->executeInTransaction("QmlAnchors::removeAnchor", [this, sourceAnchorLine](){
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors remove anchor",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
|
qmlItemNode().view()->executeInTransaction("QmlAnchors::removeAnchor", [this, sourceAnchorLine]() {
|
||||||
if (qmlItemNode().isInBaseState()) {
|
if (qmlItemNode().isInBaseState()) {
|
||||||
const PropertyNameView propertyName = anchorPropertyName(sourceAnchorLine);
|
const PropertyNameView propertyName = anchorPropertyName(sourceAnchorLine);
|
||||||
if (qmlItemNode().modelNode().hasProperty("anchors.fill")
|
if (qmlItemNode().modelNode().hasProperty("anchors.fill")
|
||||||
@@ -349,9 +420,15 @@ void QmlAnchors::removeAnchor(AnchorLineType sourceAnchorLine)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAnchors::removeAnchors()
|
void QmlAnchors::removeAnchors(SL sl)
|
||||||
{
|
{
|
||||||
qmlItemNode().view()->executeInTransaction("QmlAnchors::removeAnchors", [this](){
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors remove anchors",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
|
qmlItemNode().view()->executeInTransaction("QmlAnchors::removeAnchors", [this]() {
|
||||||
if (qmlItemNode().nodeInstance().hasAnchor("anchors.fill"))
|
if (qmlItemNode().nodeInstance().hasAnchor("anchors.fill"))
|
||||||
qmlItemNode().modelNode().removeProperty("anchors.fill");
|
qmlItemNode().modelNode().removeProperty("anchors.fill");
|
||||||
if (qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn"))
|
if (qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn"))
|
||||||
@@ -373,8 +450,14 @@ void QmlAnchors::removeAnchors()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlAnchors::instanceHasAnchor(AnchorLineType sourceAnchorLine) const
|
bool QmlAnchors::instanceHasAnchor(AnchorLineType sourceAnchorLine, SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors instance has anchor",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
if (!qmlItemNode().isValid())
|
if (!qmlItemNode().isValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -390,55 +473,102 @@ bool QmlAnchors::instanceHasAnchor(AnchorLineType sourceAnchorLine) const
|
|||||||
return qmlItemNode().nodeInstance().hasAnchor(propertyName);
|
return qmlItemNode().nodeInstance().hasAnchor(propertyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlAnchors::instanceHasAnchors() const
|
bool QmlAnchors::instanceHasAnchors(SL sl) const
|
||||||
{
|
{
|
||||||
return instanceHasAnchor(AnchorLineLeft) ||
|
using NanotraceHR::keyValue;
|
||||||
instanceHasAnchor(AnchorLineRight) ||
|
NanotraceHR::Tracer tracer{"qml anchors instance has anchors",
|
||||||
instanceHasAnchor(AnchorLineTop) ||
|
category(),
|
||||||
instanceHasAnchor(AnchorLineBottom) ||
|
keyValue("model node", *this),
|
||||||
instanceHasAnchor(AnchorLineHorizontalCenter) ||
|
keyValue("caller location", sl)};
|
||||||
instanceHasAnchor(AnchorLineVerticalCenter) ||
|
|
||||||
instanceHasAnchor(AnchorLineBaseline);
|
return instanceHasAnchor(AnchorLineLeft) || instanceHasAnchor(AnchorLineRight)
|
||||||
|
|| instanceHasAnchor(AnchorLineTop) || instanceHasAnchor(AnchorLineBottom)
|
||||||
|
|| instanceHasAnchor(AnchorLineHorizontalCenter)
|
||||||
|
|| instanceHasAnchor(AnchorLineVerticalCenter) || instanceHasAnchor(AnchorLineBaseline);
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF contentRect(const NodeInstance &nodeInstance)
|
static QRectF contentRect(const NodeInstance &nodeInstance)
|
||||||
{
|
{
|
||||||
QRectF contentRect(nodeInstance.position(), nodeInstance.size());
|
QRectF contentRect(nodeInstance.position(), nodeInstance.size());
|
||||||
return nodeInstance.contentTransform().mapRect(contentRect);
|
return nodeInstance.contentTransform().mapRect(contentRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
double QmlAnchors::instanceLeftAnchorLine() const
|
double QmlAnchors::instanceLeftAnchorLine(SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors instance left anchor line",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
return contentRect(qmlItemNode().nodeInstance()).x();
|
return contentRect(qmlItemNode().nodeInstance()).x();
|
||||||
}
|
}
|
||||||
|
|
||||||
double QmlAnchors::instanceTopAnchorLine() const
|
double QmlAnchors::instanceTopAnchorLine(SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors instance top anchor line",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
return contentRect(qmlItemNode().nodeInstance()).y();
|
return contentRect(qmlItemNode().nodeInstance()).y();
|
||||||
}
|
}
|
||||||
|
|
||||||
double QmlAnchors::instanceRightAnchorLine() const
|
double QmlAnchors::instanceRightAnchorLine(SL sl) const
|
||||||
{
|
{
|
||||||
return contentRect(qmlItemNode().nodeInstance()).x() + contentRect(qmlItemNode().nodeInstance()).width();
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors instance right anchor line",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
|
return contentRect(qmlItemNode().nodeInstance()).x()
|
||||||
|
+ contentRect(qmlItemNode().nodeInstance()).width();
|
||||||
}
|
}
|
||||||
|
|
||||||
double QmlAnchors::instanceBottomAnchorLine() const
|
double QmlAnchors::instanceBottomAnchorLine(SL sl) const
|
||||||
{
|
{
|
||||||
return contentRect(qmlItemNode().nodeInstance()).y() + contentRect(qmlItemNode().nodeInstance()).height();
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors instance bottom anchor line",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
|
return contentRect(qmlItemNode().nodeInstance()).y()
|
||||||
|
+ contentRect(qmlItemNode().nodeInstance()).height();
|
||||||
}
|
}
|
||||||
|
|
||||||
double QmlAnchors::instanceHorizontalCenterAnchorLine() const
|
double QmlAnchors::instanceHorizontalCenterAnchorLine(SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors instance horizontal center anchor line",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
return (instanceLeftAnchorLine() + instanceRightAnchorLine()) / 2.0;
|
return (instanceLeftAnchorLine() + instanceRightAnchorLine()) / 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double QmlAnchors::instanceVerticalCenterAnchorLine() const
|
double QmlAnchors::instanceVerticalCenterAnchorLine(SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors instance vertical center anchor line",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
return (instanceBottomAnchorLine() + instanceTopAnchorLine()) / 2.0;
|
return (instanceBottomAnchorLine() + instanceTopAnchorLine()) / 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double QmlAnchors::instanceAnchorLine(AnchorLineType anchorLine) const
|
double QmlAnchors::instanceAnchorLine(AnchorLineType anchorLine, SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors instance anchor line",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
switch (anchorLine) {
|
switch (anchorLine) {
|
||||||
case AnchorLineLeft: return instanceLeftAnchorLine();
|
case AnchorLineLeft: return instanceLeftAnchorLine();
|
||||||
case AnchorLineTop: return instanceTopAnchorLine();
|
case AnchorLineTop: return instanceTopAnchorLine();
|
||||||
@@ -450,14 +580,26 @@ double QmlAnchors::instanceAnchorLine(AnchorLineType anchorLine) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAnchors::setMargin(AnchorLineType sourceAnchorLineType, double margin) const
|
void QmlAnchors::setMargin(AnchorLineType sourceAnchorLineType, double margin, SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors set margin",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
PropertyNameView propertyName = marginPropertyName(sourceAnchorLineType);
|
PropertyNameView propertyName = marginPropertyName(sourceAnchorLineType);
|
||||||
qmlItemNode().setVariantProperty(propertyName, qRound(margin));
|
qmlItemNode().setVariantProperty(propertyName, qRound(margin));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlAnchors::instanceHasMargin(AnchorLineType sourceAnchorLineType) const
|
bool QmlAnchors::instanceHasMargin(AnchorLineType sourceAnchorLineType, SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors instance has margin",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
return !qIsNull(instanceMargin(sourceAnchorLineType));
|
return !qIsNull(instanceMargin(sourceAnchorLineType));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,38 +658,68 @@ static bool checkForVerticalCycleRecusive(const QmlAnchors &anchors, QList<QmlIt
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlAnchors::checkForHorizontalCycle(const QmlItemNode &sourceItem) const
|
bool QmlAnchors::checkForHorizontalCycle(const QmlItemNode &sourceItem, SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors check for horizontal cycle",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
QList<QmlItemNode> visitedItems;
|
QList<QmlItemNode> visitedItems;
|
||||||
visitedItems.append(sourceItem);
|
visitedItems.append(sourceItem);
|
||||||
|
|
||||||
return checkForHorizontalCycleRecusive(*this, visitedItems);
|
return checkForHorizontalCycleRecusive(*this, visitedItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlAnchors::checkForVerticalCycle(const QmlItemNode &sourceItem) const
|
bool QmlAnchors::checkForVerticalCycle(const QmlItemNode &sourceItem, SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors check for vertical cycle",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
QList<QmlItemNode> visitedItems;
|
QList<QmlItemNode> visitedItems;
|
||||||
visitedItems.append(sourceItem);
|
visitedItems.append(sourceItem);
|
||||||
|
|
||||||
return checkForVerticalCycleRecusive(*this, visitedItems);
|
return checkForVerticalCycleRecusive(*this, visitedItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
double QmlAnchors::instanceMargin(AnchorLineType sourceAnchorLineType) const
|
double QmlAnchors::instanceMargin(AnchorLineType sourceAnchorLineType, SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors instance margin",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
return qmlItemNode().nodeInstance().property(marginPropertyName(sourceAnchorLineType)).toDouble();
|
return qmlItemNode().nodeInstance().property(marginPropertyName(sourceAnchorLineType)).toDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAnchors::removeMargin(AnchorLineType sourceAnchorLineType)
|
void QmlAnchors::removeMargin(AnchorLineType sourceAnchorLineType, SL sl)
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors remove margin",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
if (qmlItemNode().isInBaseState()) {
|
if (qmlItemNode().isInBaseState()) {
|
||||||
PropertyNameView propertyName = marginPropertyName(sourceAnchorLineType);
|
PropertyNameView propertyName = marginPropertyName(sourceAnchorLineType);
|
||||||
qmlItemNode().modelNode().removeProperty(propertyName);
|
qmlItemNode().modelNode().removeProperty(propertyName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAnchors::removeMargins()
|
void QmlAnchors::removeMargins(SL sl)
|
||||||
{
|
{
|
||||||
qmlItemNode().view()->executeInTransaction("QmlAnchors::removeMargins", [this](){
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors remove margins",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
|
qmlItemNode().view()->executeInTransaction("QmlAnchors::removeMargins", [this]() {
|
||||||
removeMargin(AnchorLineLeft);
|
removeMargin(AnchorLineLeft);
|
||||||
removeMargin(AnchorLineRight);
|
removeMargin(AnchorLineRight);
|
||||||
removeMargin(AnchorLineTop);
|
removeMargin(AnchorLineTop);
|
||||||
@@ -557,24 +729,42 @@ void QmlAnchors::removeMargins()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAnchors::fill()
|
void QmlAnchors::fill(SL sl)
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors fill",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
if (instanceHasAnchors())
|
if (instanceHasAnchors())
|
||||||
removeAnchors();
|
removeAnchors();
|
||||||
|
|
||||||
qmlItemNode().modelNode().bindingProperty("anchors.fill").setExpression(QLatin1String("parent"));
|
qmlItemNode().modelNode().bindingProperty("anchors.fill").setExpression(QLatin1String("parent"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlAnchors::centerIn()
|
void QmlAnchors::centerIn(SL sl)
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors center in",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
if (instanceHasAnchors())
|
if (instanceHasAnchors())
|
||||||
removeAnchors();
|
removeAnchors();
|
||||||
|
|
||||||
qmlItemNode().modelNode().bindingProperty("anchors.centerIn").setExpression(QLatin1String("parent"));
|
qmlItemNode().modelNode().bindingProperty("anchors.centerIn").setExpression(QLatin1String("parent"));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlAnchors::checkForCycle(AnchorLineType anchorLineTyp, const QmlItemNode &sourceItem) const
|
bool QmlAnchors::checkForCycle(AnchorLineType anchorLineTyp, const QmlItemNode &sourceItem, SL sl) const
|
||||||
{
|
{
|
||||||
|
using NanotraceHR::keyValue;
|
||||||
|
NanotraceHR::Tracer tracer{"qml anchors check for cycle",
|
||||||
|
category(),
|
||||||
|
keyValue("model node", *this),
|
||||||
|
keyValue("caller location", sl)};
|
||||||
|
|
||||||
if (anchorLineTyp & AnchorLineHorizontalMask)
|
if (anchorLineTyp & AnchorLineHorizontalMask)
|
||||||
return checkForHorizontalCycle(sourceItem);
|
return checkForHorizontalCycle(sourceItem);
|
||||||
else
|
else
|
||||||
|
@@ -11,50 +11,60 @@ namespace QmlDesigner {
|
|||||||
|
|
||||||
class QMLDESIGNER_EXPORT QmlAnchors
|
class QMLDESIGNER_EXPORT QmlAnchors
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
using SL = ModelTracing::SourceLocation;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QmlAnchors(const QmlItemNode &fxItemNode);
|
QmlAnchors(const QmlItemNode &fxItemNode);
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid(SL sl = {}) const;
|
||||||
|
|
||||||
void setAnchor(AnchorLineType sourceAnchorLineType,
|
void setAnchor(AnchorLineType sourceAnchorLineType,
|
||||||
const QmlItemNode &targetModelNode,
|
const QmlItemNode &targetModelNode,
|
||||||
AnchorLineType targetAnchorLineType);
|
AnchorLineType targetAnchorLineType,
|
||||||
bool canAnchor(const QmlItemNode &targetModelNode) const;
|
SL sl = {});
|
||||||
|
bool canAnchor(const QmlItemNode &targetModelNode, SL sl = {}) const;
|
||||||
AnchorLineType possibleAnchorLines(AnchorLineType sourceAnchorLineType,
|
AnchorLineType possibleAnchorLines(AnchorLineType sourceAnchorLineType,
|
||||||
const QmlItemNode &targetModelNode) const;
|
const QmlItemNode &targetModelNode,
|
||||||
AnchorLine instanceAnchor(AnchorLineType sourceAnchorLineType) const;
|
SL sl = {}) const;
|
||||||
|
AnchorLine instanceAnchor(AnchorLineType sourceAnchorLineType, SL sl = {}) const;
|
||||||
|
|
||||||
void removeAnchor(AnchorLineType sourceAnchorLineType);
|
void removeAnchor(AnchorLineType sourceAnchorLineType, SL sl = {});
|
||||||
void removeAnchors();
|
void removeAnchors(SL sl = {});
|
||||||
bool instanceHasAnchor(AnchorLineType sourceAnchorLineType) const;
|
bool instanceHasAnchor(AnchorLineType sourceAnchorLineType, SL sl = {}) const;
|
||||||
bool instanceHasAnchors() const;
|
bool instanceHasAnchors(SL sl = {}) const;
|
||||||
double instanceLeftAnchorLine() const;
|
double instanceLeftAnchorLine(SL sl = {}) const;
|
||||||
double instanceTopAnchorLine() const;
|
double instanceTopAnchorLine(SL sl = {}) const;
|
||||||
double instanceRightAnchorLine() const;
|
double instanceRightAnchorLine(SL sl = {}) const;
|
||||||
double instanceBottomAnchorLine() const;
|
double instanceBottomAnchorLine(SL sl = {}) const;
|
||||||
double instanceHorizontalCenterAnchorLine() const;
|
double instanceHorizontalCenterAnchorLine(SL sl = {}) const;
|
||||||
double instanceVerticalCenterAnchorLine() const;
|
double instanceVerticalCenterAnchorLine(SL sl = {}) const;
|
||||||
double instanceAnchorLine(AnchorLineType anchorLine) const;
|
double instanceAnchorLine(AnchorLineType anchorLine, SL sl = {}) const;
|
||||||
|
|
||||||
void setMargin(AnchorLineType sourceAnchorLineType, double margin) const;
|
void setMargin(AnchorLineType sourceAnchorLineType, double margin, SL sl = {}) const;
|
||||||
bool instanceHasMargin(AnchorLineType sourceAnchorLineType) const;
|
bool instanceHasMargin(AnchorLineType sourceAnchorLineType, SL sl = {}) const;
|
||||||
double instanceMargin(AnchorLineType sourceAnchorLineType) const;
|
double instanceMargin(AnchorLineType sourceAnchorLineType, SL sl = {}) const;
|
||||||
void removeMargin(AnchorLineType sourceAnchorLineType);
|
void removeMargin(AnchorLineType sourceAnchorLineType, SL sl = {});
|
||||||
void removeMargins();
|
void removeMargins(SL sl = {});
|
||||||
|
|
||||||
void fill();
|
void fill(SL sl = {});
|
||||||
void centerIn();
|
void centerIn(SL sl = {});
|
||||||
|
|
||||||
bool checkForCycle(AnchorLineType anchorLineTyp, const QmlItemNode &sourceItem) const;
|
bool checkForCycle(AnchorLineType anchorLineTyp, const QmlItemNode &sourceItem, SL sl = {}) const;
|
||||||
bool checkForHorizontalCycle(const QmlItemNode &sourceItem) const;
|
bool checkForHorizontalCycle(const QmlItemNode &sourceItem, SL sl = {}) const;
|
||||||
bool checkForVerticalCycle(const QmlItemNode &sourceItem) const;
|
bool checkForVerticalCycle(const QmlItemNode &sourceItem, SL sl = {}) const;
|
||||||
|
|
||||||
QmlItemNode qmlItemNode() const;
|
QmlItemNode qmlItemNode() const;
|
||||||
|
|
||||||
bool modelHasAnchors() const;
|
bool modelHasAnchors(SL sl = {}) const;
|
||||||
bool modelHasAnchor(AnchorLineType sourceAnchorLineType) const;
|
bool modelHasAnchor(AnchorLineType sourceAnchorLineType, SL sl = {}) const;
|
||||||
AnchorLine modelAnchor(AnchorLineType sourceAnchorLineType) const;
|
AnchorLine modelAnchor(AnchorLineType sourceAnchorLineType, SL sl = {}) const;
|
||||||
|
|
||||||
|
template<typename String>
|
||||||
|
friend void convertToString(String &string, const QmlAnchors &anchors)
|
||||||
|
{
|
||||||
|
convertToString(string, anchors.m_qmlItemNode);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QmlItemNode m_qmlItemNode;
|
QmlItemNode m_qmlItemNode;
|
||||||
|
Reference in New Issue
Block a user