forked from qt-creator/qt-creator
QmlDesigner: draw FormEditorItem bounding rectangle
Draw red rectangle around FormEditorItems Optimize drawing using square root based sizes Task-number: QDS-2241 Change-Id: Iedd11b7e50f23e2d8c5a26ad5f7da62756ad426e Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
#include <QStyleOptionGraphicsItem>
|
||||
#include <QTimeLine>
|
||||
#include <QGraphicsView>
|
||||
#include <QtMath>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@@ -57,8 +58,8 @@ const int blockRadius = 18;
|
||||
const int blockAdjust = 40;
|
||||
const int startItemOffset = 96;
|
||||
|
||||
const qreal fontSize = 10; // points
|
||||
const qreal zoomLevelLabel = 0.5; // Everything lower than that will hide all labels
|
||||
const qreal labelFontSize = 10;
|
||||
const qreal labelShowThreshold = 0.25; // Everything lower than that will hide all labels
|
||||
const qreal defaultDpi = 96.0;
|
||||
|
||||
void drawIcon(QPainter *painter,
|
||||
@@ -627,12 +628,68 @@ void FormEditorFlowItem::updateGeometry()
|
||||
}
|
||||
}
|
||||
|
||||
void FormEditorFlowItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
{
|
||||
FormEditorItem::paint(painter, option, widget);
|
||||
|
||||
if (!painter->isActive())
|
||||
return;
|
||||
|
||||
if (!qmlItemNode().isValid())
|
||||
return;
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QPen pen;
|
||||
pen.setJoinStyle(Qt::MiterJoin);
|
||||
|
||||
QColor flowColor(0xe71919);
|
||||
|
||||
if (qmlItemNode().rootModelNode().hasAuxiliaryData("areaColor"))
|
||||
flowColor = qmlItemNode().rootModelNode().auxiliaryData("areaColor").value<QColor>();
|
||||
|
||||
if (qmlItemNode().modelNode().hasAuxiliaryData("color"))
|
||||
flowColor = qmlItemNode().modelNode().auxiliaryData("color").value<QColor>();
|
||||
|
||||
pen.setColor(flowColor);
|
||||
|
||||
qreal width = 2;
|
||||
|
||||
// if (qmlItemNode().modelNode().hasAuxiliaryData("width"))
|
||||
// width = qmlItemNode().modelNode().auxiliaryData("width").toInt();
|
||||
|
||||
width *= getLineScaleFactor();
|
||||
|
||||
pen.setWidthF(width);
|
||||
|
||||
|
||||
bool dash = false;
|
||||
|
||||
if (qmlItemNode().modelNode().hasAuxiliaryData("dash"))
|
||||
dash = qmlItemNode().modelNode().auxiliaryData("dash").toBool();
|
||||
|
||||
if (dash)
|
||||
pen.setStyle(Qt::DashLine);
|
||||
else
|
||||
pen.setStyle(Qt::SolidLine);
|
||||
|
||||
pen.setCosmetic(false);
|
||||
painter->setPen(pen);
|
||||
|
||||
QColor fillColor = QColor(Qt::transparent);
|
||||
painter->setBrush(fillColor);
|
||||
|
||||
painter->drawRoundedRect(boundingRect(), blockRadius, blockRadius);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QPointF FormEditorFlowItem::instancePosition() const
|
||||
{
|
||||
return qmlItemNode().flowPosition();
|
||||
}
|
||||
|
||||
|
||||
void FormEditorFlowActionItem::setDataModelPosition(const QPointF &position)
|
||||
{
|
||||
qmlItemNode().setPosition(position);
|
||||
@@ -691,7 +748,6 @@ void FormEditorFlowActionItem::paint(QPainter *painter, const QStyleOptionGraphi
|
||||
|
||||
QPen pen;
|
||||
pen.setJoinStyle(Qt::MiterJoin);
|
||||
pen.setCosmetic(true);
|
||||
|
||||
QColor flowColor(0xe71919);
|
||||
|
||||
@@ -706,8 +762,9 @@ void FormEditorFlowActionItem::paint(QPainter *painter, const QStyleOptionGraphi
|
||||
if (qmlItemNode().modelNode().hasAuxiliaryData("width"))
|
||||
width = qmlItemNode().modelNode().auxiliaryData("width").toInt();
|
||||
|
||||
bool dash = false;
|
||||
width *= getLineScaleFactor();
|
||||
|
||||
bool dash = false;
|
||||
|
||||
if (qmlItemNode().modelNode().hasAuxiliaryData("dash"))
|
||||
dash = qmlItemNode().modelNode().auxiliaryData("dash").toBool();
|
||||
@@ -719,7 +776,7 @@ void FormEditorFlowActionItem::paint(QPainter *painter, const QStyleOptionGraphi
|
||||
pen.setStyle(Qt::SolidLine);
|
||||
|
||||
pen.setWidthF(width);
|
||||
pen.setCosmetic(true);
|
||||
pen.setCosmetic(false);
|
||||
painter->setPen(pen);
|
||||
|
||||
QColor fillColor = QColor(Qt::transparent);
|
||||
@@ -867,10 +924,8 @@ class ConnectionConfiguration
|
||||
public:
|
||||
ConnectionConfiguration(const QmlItemNode &node,
|
||||
const ResolveConnection &resolveConnection,
|
||||
const qreal scaleFactor,
|
||||
bool hitTest = false)
|
||||
: width(2)
|
||||
, adjustedWidth(width / scaleFactor)
|
||||
, color(QColor(0xe71919))
|
||||
, lineBrush(QBrush(color))
|
||||
, penStyle(Qt::SolidLine)
|
||||
@@ -883,9 +938,10 @@ public:
|
||||
, breakOffset(50)
|
||||
, radius(8)
|
||||
, bezier(50)
|
||||
, fontSize(labelFontSize)
|
||||
, type(ConnectionType::Default)
|
||||
, label()
|
||||
, labelOffset(14 / scaleFactor)
|
||||
, labelOffset(14)
|
||||
, labelPosition(50.0)
|
||||
, labelFlags(Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextDontClip)
|
||||
, labelFlipSide(false)
|
||||
@@ -895,12 +951,12 @@ public:
|
||||
{
|
||||
// width
|
||||
if (node.modelNode().hasAuxiliaryData("width"))
|
||||
width = node.modelNode().auxiliaryData("width").toInt();
|
||||
width = node.modelNode().auxiliaryData("width").toFloat();
|
||||
// adjusted width
|
||||
if (node.modelNode().isSelected())
|
||||
width += 2;
|
||||
if (hitTest)
|
||||
width = width * 8 / scaleFactor;
|
||||
width = width * 8;
|
||||
// color
|
||||
if (resolveConnection.isStartLine)
|
||||
color = QColor("blue");
|
||||
@@ -966,7 +1022,6 @@ public:
|
||||
}
|
||||
|
||||
qreal width;
|
||||
qreal adjustedWidth;
|
||||
QColor color; // TODO private/setter
|
||||
QBrush lineBrush;
|
||||
Qt::PenStyle penStyle;
|
||||
@@ -980,6 +1035,7 @@ public:
|
||||
int breakOffset;
|
||||
int radius;
|
||||
int bezier;
|
||||
qreal fontSize;
|
||||
ConnectionType type;
|
||||
QString label;
|
||||
qreal labelOffset;
|
||||
@@ -1285,7 +1341,7 @@ public:
|
||||
const bool boolExitRight = fromRect.right() < toRect.center().x();
|
||||
const bool boolExitBottom = fromRect.bottom() < toRect.center().y();
|
||||
|
||||
const qreal padding = 8;
|
||||
const int padding = 4 * config.width;
|
||||
|
||||
if (horizontalFirst) {
|
||||
const qreal startX = boolExitRight ? fromRect.right() + padding : fromRect.x() - padding;
|
||||
@@ -1405,7 +1461,7 @@ void FormEditorTransitionItem::updateGeometry()
|
||||
QPixmap pixmap(640, 480);
|
||||
QPainter localPainter(&pixmap);
|
||||
QFont font = localPainter.font();
|
||||
font.setPointSizeF(getFontSize(&localPainter) / getScaleFactor());
|
||||
font.setPixelSize(labelFontSize * getTextScaleFactor());
|
||||
localPainter.setFont(font);
|
||||
|
||||
const auto fromNodes = resolved.from;
|
||||
@@ -1481,7 +1537,7 @@ void FormEditorTransitionItem::drawSingleLabel(QPainter *painter, const Connecti
|
||||
QPointF position;
|
||||
qreal angle;
|
||||
|
||||
const qreal hMargin = 10.0 / getScaleFactor();
|
||||
const qreal hMargin = 10.0 * getItemScaleFactor();
|
||||
QFontMetrics metric(painter->font());
|
||||
|
||||
const qreal lineHeight = metric.boundingRect("Xyz").height();
|
||||
@@ -1506,7 +1562,7 @@ void FormEditorTransitionItem::drawSingleLabel(QPainter *painter, const Connecti
|
||||
labelRect.adjust(-hMargin, 0.0, hMargin, 0.0);
|
||||
|
||||
if (singleEvent && singleSignal)
|
||||
labelRect.setHeight(eventRect.height() + signalRect.height() + (6.0 / getScaleFactor()));
|
||||
labelRect.setHeight(eventRect.height() + signalRect.height() + (6.0 * getTextScaleFactor()));
|
||||
|
||||
const qreal halfHeight = labelRect.height() * 0.5;
|
||||
|
||||
@@ -1526,7 +1582,7 @@ void FormEditorTransitionItem::drawSingleLabel(QPainter *painter, const Connecti
|
||||
|
||||
// Calculate font bounding box without taking into account the cale factor
|
||||
QFont originalFont = painter->font();
|
||||
originalFont.setPointSizeF(getFontSize(painter));
|
||||
originalFont.setPixelSize(labelFontSize * getTextScaleFactor());
|
||||
QFontMetrics originalMetric(originalFont);
|
||||
QRectF originalTextRect = originalMetric.boundingRect(events);
|
||||
originalTextRect.adjust(-10.0, 0.0, 10.0, 0.0);
|
||||
@@ -1588,9 +1644,9 @@ void FormEditorTransitionItem::drawSingleLabel(QPainter *painter, const Connecti
|
||||
painter->setPen(Qt::white);
|
||||
if (singleEvent && singleSignal) {
|
||||
eventRect.setWidth(labelRect.width());
|
||||
eventRect.moveTopLeft(labelRect.topLeft() + QPointF(0.0, 4.0 / getScaleFactor()));
|
||||
eventRect.moveTopLeft(labelRect.topLeft() + QPointF(0.0, 4.0 * getItemScaleFactor()));
|
||||
signalRect.setWidth(labelRect.width());
|
||||
signalRect.moveBottomLeft(labelRect.bottomLeft() - QPointF(0.0, 4.0 / getScaleFactor()));
|
||||
signalRect.moveBottomLeft(labelRect.bottomLeft() - QPointF(0.0, 4.0 * getItemScaleFactor()));
|
||||
|
||||
painter->drawText(eventRect, Qt::AlignCenter, events);
|
||||
painter->drawText(signalRect, Qt::AlignCenter, targetSignal);
|
||||
@@ -1619,9 +1675,8 @@ void FormEditorTransitionItem::drawSelectionLabel(QPainter *painter, const Conne
|
||||
const QStringList events = connection.config.events.split(',');
|
||||
const int eventCount = events.size();
|
||||
|
||||
const qreal scaleFactor = getScaleFactor();
|
||||
const qreal radius = 7.0 / scaleFactor;
|
||||
const qreal hMargin = 10.0 / scaleFactor;
|
||||
const qreal radius = 7.0 * getItemScaleFactor();
|
||||
const qreal hMargin = 10.0 * getItemScaleFactor();
|
||||
|
||||
QFontMetrics metric(painter->font());
|
||||
const qreal lineHeight = metric.boundingRect("Xyz").height();
|
||||
@@ -1657,7 +1712,7 @@ void FormEditorTransitionItem::drawSelectionLabel(QPainter *painter, const Conne
|
||||
}
|
||||
|
||||
const int signalCount = signalList.size();
|
||||
const qreal offset = 10.0 / scaleFactor;
|
||||
const qreal offset = 10.0 * getItemScaleFactor();
|
||||
|
||||
qreal totalHeight = 0;
|
||||
if (hasEvents)
|
||||
@@ -1730,34 +1785,33 @@ void FormEditorTransitionItem::drawSelectionLabel(QPainter *painter, const Conne
|
||||
static void drawArrow(QPainter *painter,
|
||||
const QPointF &point,
|
||||
const qreal &angle,
|
||||
const qreal &arrowLength,
|
||||
const qreal &arrowWidth)
|
||||
qreal arrowSize,
|
||||
qreal arrowTipAngle = 90.0)
|
||||
{
|
||||
const QPointF peakP(0, 0);
|
||||
const QPointF leftP(-arrowLength, -arrowWidth * 0.5);
|
||||
const QPointF rightP(-arrowLength, arrowWidth * 0.5);
|
||||
const QPointF endP(-arrowSize, 0);
|
||||
|
||||
painter->save();
|
||||
|
||||
painter->translate(point);
|
||||
painter->rotate(-angle);
|
||||
painter->drawLine(leftP, peakP);
|
||||
painter->drawLine(rightP, peakP);
|
||||
painter->rotate(-angle - (arrowTipAngle/2.0));
|
||||
painter->drawLine(peakP, endP);
|
||||
painter->rotate(arrowTipAngle);
|
||||
painter->drawLine(peakP, endP);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void FormEditorTransitionItem::paintConnection(QPainter *painter, const Connection &connection)
|
||||
{
|
||||
const qreal arrowLength = 4 * connection.config.adjustedWidth;
|
||||
const qreal arrowWidth = 8 * connection.config.adjustedWidth;
|
||||
const int arrowSize = 12 * getLineScaleFactor();
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
// Draw path/connection line
|
||||
QPen pen;
|
||||
pen.setCosmetic(true);
|
||||
pen.setCosmetic(false);
|
||||
pen.setJoinStyle(Qt::MiterJoin);
|
||||
pen.setCapStyle(Qt::RoundCap);
|
||||
pen.setBrush(connection.config.lineBrush);
|
||||
@@ -1769,12 +1823,12 @@ void FormEditorTransitionItem::paintConnection(QPainter *painter, const Connecti
|
||||
pen.setStyle(connection.config.penStyle);
|
||||
}
|
||||
|
||||
pen.setWidthF(connection.config.width);
|
||||
pen.setWidthF(connection.config.width * getLineScaleFactor());
|
||||
painter->setPen(pen);
|
||||
|
||||
painter->drawPath(connection.path);
|
||||
|
||||
pen.setWidthF(connection.config.width);
|
||||
pen.setWidthF(connection.config.width * getLineScaleFactor());
|
||||
pen.setStyle(Qt::SolidLine);
|
||||
pen.setColor(connection.config.color);
|
||||
painter->setPen(pen);
|
||||
@@ -1791,16 +1845,16 @@ void FormEditorTransitionItem::paintConnection(QPainter *painter, const Connecti
|
||||
}
|
||||
|
||||
if (connection.config.drawEnd)
|
||||
drawArrow(painter, connection.end, angle, arrowLength, arrowWidth);
|
||||
drawArrow(painter, connection.end, angle, arrowSize, 60.0);
|
||||
|
||||
// Draw start ellipse
|
||||
if (connection.config.drawStart) {
|
||||
painter->setBrush(Qt::white);
|
||||
painter->drawEllipse(connection.start, arrowLength / 2.0, arrowLength / 2.0);
|
||||
painter->drawEllipse(connection.start, arrowSize / 5, arrowSize / 5);
|
||||
}
|
||||
|
||||
// Draw labels
|
||||
if (viewportTransform().m11() >= zoomLevelLabel)
|
||||
if (viewportTransform().m11() >= labelShowThreshold)
|
||||
drawLabels(painter, connection);
|
||||
|
||||
painter->restore();
|
||||
@@ -1825,11 +1879,11 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi
|
||||
if (!isModelNodeValid(resolved.from))
|
||||
return;
|
||||
|
||||
ConnectionConfiguration config(qmlItemNode(), resolved, viewportTransform().m11(), m_hitTest);
|
||||
ConnectionConfiguration config(qmlItemNode(), resolved, m_hitTest);
|
||||
|
||||
QFont f = painter->font();
|
||||
f.setPointSizeF(getFontSize(painter) / getScaleFactor());
|
||||
painter->setFont(f);
|
||||
QFont font = painter->font();
|
||||
font.setPixelSize(config.fontSize * getTextScaleFactor());
|
||||
painter->setFont(font);
|
||||
|
||||
const auto fromNodes = resolved.from;
|
||||
const auto toNodes = resolved.to;
|
||||
@@ -1896,7 +1950,7 @@ void FormEditorTransitionItem::paint(QPainter *painter, const QStyleOptionGraphi
|
||||
const QString icon = Theme::getIconUnicode(Theme::startNode);
|
||||
|
||||
QPen pen;
|
||||
pen.setCosmetic(true);
|
||||
pen.setCosmetic(false);
|
||||
pen.setColor(config.color);
|
||||
painter->setPen(pen);
|
||||
|
||||
@@ -1937,18 +1991,19 @@ QTransform FormEditorItem::viewportTransform() const
|
||||
return scene()->views().first()->viewportTransform();
|
||||
}
|
||||
|
||||
qreal FormEditorItem::getFontSize(QPainter *painter) const
|
||||
qreal FormEditorItem::getItemScaleFactor() const
|
||||
{
|
||||
const int dpi = std::max(painter->device()->logicalDpiX(),
|
||||
painter->device()->logicalDpiY());
|
||||
|
||||
return fontSize * (dpi / defaultDpi);
|
||||
return 1.0 / viewportTransform().m11();
|
||||
}
|
||||
|
||||
qreal FormEditorItem::getScaleFactor() const
|
||||
qreal FormEditorItem::getLineScaleFactor() const
|
||||
{
|
||||
// Cap scaling at 100% zoom
|
||||
return (viewportTransform().m11() >= 1.0) ? viewportTransform().m11() : 1.0;
|
||||
return 2 / qSqrt(viewportTransform().m11());
|
||||
}
|
||||
|
||||
qreal FormEditorItem::getTextScaleFactor() const
|
||||
{
|
||||
return 2 / qSqrt(viewportTransform().m11());
|
||||
}
|
||||
|
||||
void FormEditorFlowDecisionItem::updateGeometry()
|
||||
@@ -1982,7 +2037,7 @@ void FormEditorFlowDecisionItem::updateGeometry()
|
||||
QPixmap pixmap(640, 480);
|
||||
QPainter localPainter(&pixmap);
|
||||
QFont font = localPainter.font();
|
||||
font.setPointSizeF(getFontSize(&localPainter) / getScaleFactor());
|
||||
font.setPixelSize(labelFontSize * getTextScaleFactor());
|
||||
localPainter.setFont(font);
|
||||
|
||||
const qreal margin = blockAdjust * 0.5;
|
||||
@@ -2045,7 +2100,7 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap
|
||||
|
||||
QPen pen;
|
||||
pen.setJoinStyle(Qt::MiterJoin);
|
||||
pen.setCosmetic(true);
|
||||
pen.setCosmetic(false);
|
||||
|
||||
QColor flowColor(0xe71919);
|
||||
|
||||
@@ -2055,24 +2110,26 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap
|
||||
if (qmlItemNode().modelNode().hasAuxiliaryData("color"))
|
||||
flowColor = qmlItemNode().modelNode().auxiliaryData("color").value<QColor>();
|
||||
|
||||
pen.setColor(flowColor);
|
||||
|
||||
qreal width = 2;
|
||||
|
||||
if (qmlItemNode().modelNode().hasAuxiliaryData("width"))
|
||||
width = qmlItemNode().modelNode().auxiliaryData("width").toInt();
|
||||
|
||||
width *= getLineScaleFactor();
|
||||
pen.setWidthF(width);
|
||||
|
||||
bool dash = false;
|
||||
|
||||
if (qmlItemNode().modelNode().hasAuxiliaryData("dash"))
|
||||
dash = qmlItemNode().modelNode().auxiliaryData("dash").toBool();
|
||||
|
||||
pen.setColor(flowColor);
|
||||
if (dash)
|
||||
pen.setStyle(Qt::DashLine);
|
||||
else
|
||||
pen.setStyle(Qt::SolidLine);
|
||||
|
||||
pen.setWidthF(width);
|
||||
pen.setCosmetic(true);
|
||||
painter->setPen(pen);
|
||||
|
||||
QColor fillColor = QColor(Qt::transparent);
|
||||
@@ -2119,7 +2176,7 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap
|
||||
if (qmlItemNode().modelNode().hasAuxiliaryData("showDialogLabel"))
|
||||
showDialogLabel = qmlItemNode().modelNode().auxiliaryData("showDialogLabel").toBool();
|
||||
|
||||
if (showDialogLabel && viewportTransform().m11() >= zoomLevelLabel) {
|
||||
if (showDialogLabel && viewportTransform().m11() >= labelShowThreshold) {
|
||||
QString dialogTitle;
|
||||
if (qmlItemNode().modelNode().hasVariantProperty("dialogTitle"))
|
||||
dialogTitle = qmlItemNode().modelNode().variantProperty("dialogTitle").value().toString();
|
||||
@@ -2127,7 +2184,7 @@ void FormEditorFlowDecisionItem::paint(QPainter *painter, const QStyleOptionGrap
|
||||
if (!dialogTitle.isEmpty()) {
|
||||
|
||||
QFont font = painter->font();
|
||||
font.setPointSizeF(getFontSize(painter) / getScaleFactor());
|
||||
font.setPixelSize(labelFontSize * getTextScaleFactor());
|
||||
painter->setFont(font);
|
||||
|
||||
QRectF textRect(0, 0, 100, 20);
|
||||
|
@@ -128,8 +128,10 @@ protected:
|
||||
QList<FormEditorItem*> offspringFormEditorItemsRecursive(const FormEditorItem *formEditorItem) const;
|
||||
FormEditorItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene);
|
||||
QTransform viewportTransform() const;
|
||||
qreal getFontSize(QPainter *painter) const;
|
||||
qreal getScaleFactor() const;
|
||||
|
||||
qreal getItemScaleFactor() const;
|
||||
qreal getLineScaleFactor() const;
|
||||
qreal getTextScaleFactor() const;
|
||||
|
||||
QRectF m_boundingRect;
|
||||
QRectF m_paintedBoundingRect;
|
||||
@@ -161,6 +163,7 @@ public:
|
||||
void setDataModelPositionInBaseState(const QPointF &position) override;
|
||||
void updateGeometry() override;
|
||||
QPointF instancePosition() const override;
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
|
||||
|
||||
protected:
|
||||
FormEditorFlowItem(const QmlItemNode &qmlItemNode, FormEditorScene *scene)
|
||||
|
Reference in New Issue
Block a user