QmlDesigner: Add anchor tracing

Change-Id: Ie687940dbedd820cbfd5deb9323f4bad3cac0ea2
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2025-05-24 01:06:58 +02:00
parent 18d65b4546
commit 244ed5008e
4 changed files with 319 additions and 111 deletions

View File

@@ -5,6 +5,8 @@
namespace QmlDesigner {
static auto category = ModelTracing::category;
AnchorLine::AnchorLine()
: m_qmlItemNode(QmlItemNode())
, m_type(AnchorLineInvalid)
@@ -20,8 +22,11 @@ AnchorLineType AnchorLine::type() const
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();
}

View File

@@ -11,11 +11,14 @@ namespace QmlDesigner {
class QMLDESIGNER_EXPORT AnchorLine
{
protected:
using SL = ModelTracing::SourceLocation;
public:
AnchorLine();
AnchorLine(const QmlItemNode &qmlItemNode, AnchorLineType type);
AnchorLineType type() const;
bool isValid() const;
bool isValid(SL sl = {}) const;
static bool isHorizontalAnchorLine(AnchorLineType anchorline);
static bool isVerticalAnchorLine(AnchorLineType anchorline);

View File

@@ -9,6 +9,8 @@
namespace QmlDesigner {
static auto category = ModelTracing::category;
static PropertyName lineTypeToString(AnchorLineType lineType)
{
switch (lineType) {
@@ -114,19 +116,28 @@ QmlItemNode QmlAnchors::qmlItemNode() const
return m_qmlItemNode;
}
bool QmlAnchors::modelHasAnchors() const
bool QmlAnchors::modelHasAnchors(SL sl) const
{
return modelHasAnchor(AnchorLineLeft)
|| modelHasAnchor(AnchorLineRight)
|| modelHasAnchor(AnchorLineTop)
|| modelHasAnchor(AnchorLineBottom)
|| modelHasAnchor(AnchorLineHorizontalCenter)
|| modelHasAnchor(AnchorLineVerticalCenter)
|| modelHasAnchor(AnchorLineBaseline);
using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"qml anchors has anchors",
category(),
keyValue("model node", *this),
keyValue("caller location", sl)};
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);
if (sourceAnchorLineType & AnchorLineFill)
@@ -138,20 +149,37 @@ bool QmlAnchors::modelHasAnchor(AnchorLineType sourceAnchorLineType) const
return qmlItemNode().modelNode().hasBindingProperty(anchorPropertyName(sourceAnchorLineType));
}
AnchorLine QmlAnchors::modelAnchor(AnchorLineType sourceAnchorLineType) const
AnchorLine QmlAnchors::modelAnchor(AnchorLineType sourceAnchorLineType, SL sl) const
{
QPair<PropertyName, ModelNode> targetAnchorLinePair;
if (sourceAnchorLineType & AnchorLineFill && qmlItemNode().modelNode().hasBindingProperty("anchors.fill")) {
targetAnchorLinePair.second = qmlItemNode().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();
}
using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"qml anchors get anchor",
category(),
keyValue("model node", *this),
keyValue("caller location", sl)};
QPair<PropertyName, ModelNode> targetAnchorLinePair;
if (sourceAnchorLineType & AnchorLineFill
&& qmlItemNode().modelNode().hasBindingProperty("anchors.fill")) {
targetAnchorLinePair.second = qmlItemNode()
.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);
@@ -162,35 +190,53 @@ AnchorLine QmlAnchors::modelAnchor(AnchorLineType sourceAnchorLineType) const
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();
}
void QmlAnchors::setAnchor(AnchorLineType sourceAnchorLine,
const QmlItemNode &targetQmlItemNode,
AnchorLineType targetAnchorLine)
const QmlItemNode &targetQmlItemNode,
AnchorLineType targetAnchorLine,
SL sl)
{
qmlItemNode().view()->executeInTransaction("QmlAnchors::setAnchor", [this, sourceAnchorLine, targetQmlItemNode, targetAnchorLine](){
if (qmlItemNode().isInBaseState()) {
if ((qmlItemNode().nodeInstance().hasAnchor("anchors.fill") && (sourceAnchorLine & AnchorLineFill))
|| ((qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn") && (sourceAnchorLine & AnchorLineCenter)))) {
removeAnchor(sourceAnchorLine);
}
using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"qml anchors set anchor",
category(),
keyValue("model node", *this),
keyValue("caller location", sl)};
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);
}
});
qmlItemNode().view()->executeInTransaction(
"QmlAnchors::setAnchor", [this, sourceAnchorLine, targetQmlItemNode, targetAnchorLine]() {
if (qmlItemNode().isInBaseState()) {
if ((qmlItemNode().nodeInstance().hasAnchor("anchors.fill")
&& (sourceAnchorLine & AnchorLineFill))
|| ((qmlItemNode().nodeInstance().hasAnchor("anchors.centerIn")
&& (sourceAnchorLine & AnchorLineCenter)))) {
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))
return true;
@@ -227,7 +273,7 @@ bool detectHorizontalCycle(const ModelNode &node, QList<ModelNode> knownNodeList
return false;
}
bool detectVerticalCycle(const ModelNode &node, QList<ModelNode> knownNodeList)
static bool detectVerticalCycle(const ModelNode &node, QList<ModelNode> knownNodeList)
{
if (!node.isValid())
return false;
@@ -267,8 +313,14 @@ bool detectVerticalCycle(const ModelNode &node, QList<ModelNode> knownNodeList)
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())
return false;
@@ -282,8 +334,15 @@ bool QmlAnchors::canAnchor(const QmlItemNode &targetModelNode) const
}
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))
return AnchorLineInvalid;
@@ -300,8 +359,14 @@ AnchorLineType QmlAnchors::possibleAnchorLines(AnchorLineType sourceAnchorLineTy
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;
if (qmlItemNode().nodeInstance().hasAnchor("anchors.fill") && (sourceAnchorLine & AnchorLineFill)) {
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);
}
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()) {
const PropertyNameView propertyName = anchorPropertyName(sourceAnchorLine);
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"))
qmlItemNode().modelNode().removeProperty("anchors.fill");
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())
return false;
@@ -390,55 +473,102 @@ bool QmlAnchors::instanceHasAnchor(AnchorLineType sourceAnchorLine) const
return qmlItemNode().nodeInstance().hasAnchor(propertyName);
}
bool QmlAnchors::instanceHasAnchors() const
bool QmlAnchors::instanceHasAnchors(SL sl) const
{
return instanceHasAnchor(AnchorLineLeft) ||
instanceHasAnchor(AnchorLineRight) ||
instanceHasAnchor(AnchorLineTop) ||
instanceHasAnchor(AnchorLineBottom) ||
instanceHasAnchor(AnchorLineHorizontalCenter) ||
instanceHasAnchor(AnchorLineVerticalCenter) ||
instanceHasAnchor(AnchorLineBaseline);
using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"qml anchors instance has anchors",
category(),
keyValue("model node", *this),
keyValue("caller location", sl)};
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());
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();
}
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();
}
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;
}
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;
}
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) {
case AnchorLineLeft: return instanceLeftAnchorLine();
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);
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));
}
@@ -516,38 +658,68 @@ static bool checkForVerticalCycleRecusive(const QmlAnchors &anchors, QList<QmlIt
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;
visitedItems.append(sourceItem);
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;
visitedItems.append(sourceItem);
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();
}
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()) {
PropertyNameView propertyName = marginPropertyName(sourceAnchorLineType);
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(AnchorLineRight);
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())
removeAnchors();
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())
removeAnchors();
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)
return checkForHorizontalCycle(sourceItem);
else

View File

@@ -11,50 +11,60 @@ namespace QmlDesigner {
class QMLDESIGNER_EXPORT QmlAnchors
{
protected:
using SL = ModelTracing::SourceLocation;
public:
QmlAnchors(const QmlItemNode &fxItemNode);
bool isValid() const;
bool isValid(SL sl = {}) const;
void setAnchor(AnchorLineType sourceAnchorLineType,
const QmlItemNode &targetModelNode,
AnchorLineType targetAnchorLineType);
bool canAnchor(const QmlItemNode &targetModelNode) const;
AnchorLineType targetAnchorLineType,
SL sl = {});
bool canAnchor(const QmlItemNode &targetModelNode, SL sl = {}) const;
AnchorLineType possibleAnchorLines(AnchorLineType sourceAnchorLineType,
const QmlItemNode &targetModelNode) const;
AnchorLine instanceAnchor(AnchorLineType sourceAnchorLineType) const;
const QmlItemNode &targetModelNode,
SL sl = {}) const;
AnchorLine instanceAnchor(AnchorLineType sourceAnchorLineType, SL sl = {}) const;
void removeAnchor(AnchorLineType sourceAnchorLineType);
void removeAnchors();
bool instanceHasAnchor(AnchorLineType sourceAnchorLineType) const;
bool instanceHasAnchors() const;
double instanceLeftAnchorLine() const;
double instanceTopAnchorLine() const;
double instanceRightAnchorLine() const;
double instanceBottomAnchorLine() const;
double instanceHorizontalCenterAnchorLine() const;
double instanceVerticalCenterAnchorLine() const;
double instanceAnchorLine(AnchorLineType anchorLine) const;
void removeAnchor(AnchorLineType sourceAnchorLineType, SL sl = {});
void removeAnchors(SL sl = {});
bool instanceHasAnchor(AnchorLineType sourceAnchorLineType, SL sl = {}) const;
bool instanceHasAnchors(SL sl = {}) const;
double instanceLeftAnchorLine(SL sl = {}) const;
double instanceTopAnchorLine(SL sl = {}) const;
double instanceRightAnchorLine(SL sl = {}) const;
double instanceBottomAnchorLine(SL sl = {}) const;
double instanceHorizontalCenterAnchorLine(SL sl = {}) const;
double instanceVerticalCenterAnchorLine(SL sl = {}) const;
double instanceAnchorLine(AnchorLineType anchorLine, SL sl = {}) const;
void setMargin(AnchorLineType sourceAnchorLineType, double margin) const;
bool instanceHasMargin(AnchorLineType sourceAnchorLineType) const;
double instanceMargin(AnchorLineType sourceAnchorLineType) const;
void removeMargin(AnchorLineType sourceAnchorLineType);
void removeMargins();
void setMargin(AnchorLineType sourceAnchorLineType, double margin, SL sl = {}) const;
bool instanceHasMargin(AnchorLineType sourceAnchorLineType, SL sl = {}) const;
double instanceMargin(AnchorLineType sourceAnchorLineType, SL sl = {}) const;
void removeMargin(AnchorLineType sourceAnchorLineType, SL sl = {});
void removeMargins(SL sl = {});
void fill();
void centerIn();
void fill(SL sl = {});
void centerIn(SL sl = {});
bool checkForCycle(AnchorLineType anchorLineTyp, const QmlItemNode &sourceItem) const;
bool checkForHorizontalCycle(const QmlItemNode &sourceItem) const;
bool checkForVerticalCycle(const QmlItemNode &sourceItem) const;
bool checkForCycle(AnchorLineType anchorLineTyp, const QmlItemNode &sourceItem, SL sl = {}) const;
bool checkForHorizontalCycle(const QmlItemNode &sourceItem, SL sl = {}) const;
bool checkForVerticalCycle(const QmlItemNode &sourceItem, SL sl = {}) const;
QmlItemNode qmlItemNode() const;
bool modelHasAnchors() const;
bool modelHasAnchor(AnchorLineType sourceAnchorLineType) const;
AnchorLine modelAnchor(AnchorLineType sourceAnchorLineType) const;
bool modelHasAnchors(SL sl = {}) const;
bool modelHasAnchor(AnchorLineType sourceAnchorLineType, SL sl = {}) 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:
QmlItemNode m_qmlItemNode;