From 4f5610297889a77c2ca128fa01450e508ac97ad1 Mon Sep 17 00:00:00 2001 From: Benjamin Guest Date: Mon, 20 Jan 2025 18:01:53 -0500 Subject: [PATCH] TechDraw: Fix dimension alignment issue. Fixes issue #19121 "dimension numbers placed lower than normal". Problem: QGCustomText has a new method `alignmentRect` which can optionally return a `tightBoundingRect` instead of the regular `boundingRect`. The `alignmentRect` is used for laying out the `QGIDatumLabel`, however QGraphicsItemGroup's `childrenBoundingRect` use the childrens' `boundingRect` and knows nothing of `alignmentRect`. The result is an improperly sized label and frame and miss alignment. Additionally `childrenBoundingRect` calculations includes hidden views, so even though the `m_tolTextOver` and `m_tolTextUnder` are hidden they still affect the bounding rect size. Solution: 1. Implement new method `QGIDatumLabel::tightBoundingRect` this calculates the bounding rect using the subview's `aligmentRect` if there is text in the custom text. 2. Use `tightBoundingRect` in place of `boundingRect` to for the drawing of arrows and the exact dim frames. 3. This PR acknowledges that there are some edge case fonts that while not clipped may not interface perfectly with arrows and the exact dimension frame. 4. Fix vertical alignment of `m_tolTextOver` / `m_tolTextUnder` 5. Incorporate PR Review comments --- src/Mod/TechDraw/Gui/QGCustomText.cpp | 2 +- src/Mod/TechDraw/Gui/QGIViewDimension.cpp | 52 +++++++++++++---------- src/Mod/TechDraw/Gui/QGIViewDimension.h | 1 + 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/Mod/TechDraw/Gui/QGCustomText.cpp b/src/Mod/TechDraw/Gui/QGCustomText.cpp index 07e13a881f..895ec1c509 100644 --- a/src/Mod/TechDraw/Gui/QGCustomText.cpp +++ b/src/Mod/TechDraw/Gui/QGCustomText.cpp @@ -178,7 +178,7 @@ void QGCustomText::paint ( QPainter * painter, const QStyleOptionGraphicsItem * myOption.state &= ~QStyle::State_Selected; // painter->setPen(Qt::green); -// painter->drawRect(boundingRect()); //good for debugging +// painter->drawRect(alignmentRect()); //good for debugging QGraphicsTextItem::paint (painter, &myOption, widget); } diff --git a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp index f426d0969e..b390dbd62d 100644 --- a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp @@ -354,18 +354,29 @@ QRectF QGIDatumLabel::boundingRect() const return childrenBoundingRect(); } +QRectF QGIDatumLabel::tightBoundingRect() const +{ + QRectF totalRect; + for (QGraphicsItem* item : m_textItems->childItems()) { + auto* customText = dynamic_cast(item); + if (customText && !customText->toPlainText().isEmpty()) { + QRectF itemRect = customText->alignmentRect(); + QPointF pos = customText->pos(); + itemRect.translate(pos.x(), pos.y()); + totalRect = totalRect.isNull() ? itemRect : totalRect.united(itemRect); + } + } + int fontSize = m_dimText->font().pixelSize(); + int paddingLeft = fontSize * 0.2; + int paddingTop = fontSize * 0.1; + int paddingRight = fontSize * 0.2; + int paddingBottom = fontSize * 0.1; + return totalRect.adjusted(-paddingLeft, -paddingTop, paddingRight, paddingBottom); +} + void QGIDatumLabel::updateFrameRect() { prepareGeometryChange(); - int fontSize = m_dimText->font().pixelSize(); - int paddingLeft = fontSize * 0.3; - int paddingTop = fontSize * 0.1; - int paddingRight = fontSize * 0.3; - int paddingBottom = fontSize * 0.125; - // Why top and bottom padding different? - // Because the m_dimText bounding box isn't relative to X height :( - // And we want padding to be relative to X height - // TODO: make QGCustomLabel::boundingBoxXHeight - m_frame->setRect(m_textItems->childrenBoundingRect().adjusted(-paddingLeft, -paddingTop, paddingRight, paddingBottom)); // Update bounding rect + m_frame->setRect(tightBoundingRect()); } void QGIDatumLabel::setLineWidth(double lineWidth) @@ -420,9 +431,7 @@ void QGIDatumLabel::setPosFromCenter(const double& xCenter, const double& yCente QRectF labelBox = m_dimText->alignmentRect(); double right = labelBox.right(); - double top = labelBox.top(); - double bottom = labelBox.bottom(); - double middle = (top + bottom) / 2.0; + double middle = labelBox.center().y(); //set unit position QRectF unitBox = m_unitText->alignmentRect(); @@ -437,10 +446,9 @@ void QGIDatumLabel::setPosFromCenter(const double& xCenter, const double& yCente // Adjust for difference in tight and original bounding box sizes, note the y-coord down system QPointF tol_adj = m_tolTextOver->tightBoundingAdjust(); - m_tolTextOver->justifyLeftAt(tolLeft + tol_adj.x(), middle - tol_adj.y(), false); + m_tolTextOver->justifyLeftAt(tolLeft + tol_adj.x(), middle + tol_adj.y()/2.0, false); tol_adj = m_tolTextUnder->tightBoundingAdjust(); - m_tolTextUnder->justifyLeftAt(tolLeft + tol_adj.x(), middle + overBox.height() - tol_adj.y(), - false); + m_tolTextUnder->justifyLeftAt(tolLeft + tol_adj.x(), middle + overBox.height() + tol_adj.y()/2.0, false); } void QGIDatumLabel::setLabelCenter() @@ -453,7 +461,7 @@ void QGIDatumLabel::setLabelCenter() Base::Vector2d QGIDatumLabel::getPosToCenterVec() { - QPointF center = boundingRect().center(); + QPointF center = tightBoundingRect().center(); return Base::Vector2d(center.x(), center.y()); } @@ -2350,7 +2358,7 @@ void QGIViewDimension::drawDistance(TechDraw::DrawViewDimension* dimension, ViewProviderDimension* viewProvider) const { Base::BoundBox2d labelRectangle( - fromQtGui(mapRectFromItem(datumLabel, datumLabel->boundingRect()))); + fromQtGui(mapRectFromItem(datumLabel, datumLabel->tightBoundingRect()))); pointPair linePoints = dimension->getLinearPoints(); const char* dimensionType = dimension->Type.getValueAsString(); @@ -2387,7 +2395,7 @@ void QGIViewDimension::drawRadius(TechDraw::DrawViewDimension* dimension, ViewProviderDimension* viewProvider) const { Base::BoundBox2d labelRectangle( - fromQtGui(mapRectFromItem(datumLabel, datumLabel->boundingRect()))); + fromQtGui(mapRectFromItem(datumLabel, datumLabel->tightBoundingRect()))); arcPoints curvePoints = dimension->getArcPoints(); double endAngle; @@ -2418,7 +2426,7 @@ void QGIViewDimension::drawDiameter(TechDraw::DrawViewDimension* dimension, ViewProviderDimension* viewProvider) const { Base::BoundBox2d labelRectangle( - fromQtGui(mapRectFromItem(datumLabel, datumLabel->boundingRect()))); + fromQtGui(mapRectFromItem(datumLabel, datumLabel->tightBoundingRect()))); Base::Vector2d labelCenter(labelRectangle.GetCenter()); arcPoints curvePoints = dimension->getArcPoints(); @@ -2585,7 +2593,7 @@ void QGIViewDimension::drawAngle(TechDraw::DrawViewDimension* dimension, QPainterPath anglePath; Base::BoundBox2d labelRectangle( - fromQtGui(mapRectFromItem(datumLabel, datumLabel->boundingRect()))); + fromQtGui(mapRectFromItem(datumLabel, datumLabel->tightBoundingRect()))); Base::Vector2d labelCenter(labelRectangle.GetCenter()); double labelAngle = 0.0; @@ -2775,7 +2783,7 @@ void QGIViewDimension::drawArea(TechDraw::DrawViewDimension* dimension, ViewProviderDimension* viewProvider) const { Base::BoundBox2d labelRectangle( - fromQtGui(mapRectFromItem(datumLabel, datumLabel->boundingRect()))); + fromQtGui(mapRectFromItem(datumLabel, datumLabel->tightBoundingRect()))); areaPoint areaPoint = dimension->getAreaPoint(); drawAreaExecutive( diff --git a/src/Mod/TechDraw/Gui/QGIViewDimension.h b/src/Mod/TechDraw/Gui/QGIViewDimension.h index 7dcb13660a..70a8efca50 100644 --- a/src/Mod/TechDraw/Gui/QGIViewDimension.h +++ b/src/Mod/TechDraw/Gui/QGIViewDimension.h @@ -69,6 +69,7 @@ public: int type() const override { return Type;} QRectF boundingRect() const override; + QRectF tightBoundingRect() const; void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; void paint( QPainter *painter, const QStyleOptionGraphicsItem *option,