diff options
author | Lukáš Lalinský <lalinsky@gmail.com> | 2008-12-12 14:41:01 +0100 |
---|---|---|
committer | Lukáš Lalinský <lalinsky@gmail.com> | 2008-12-12 14:41:01 +0100 |
commit | 1772e08823194ee25b3ebf444ef05290b6b33c68 (patch) | |
tree | 79fd31826079ffa150446c26f36cd63200bd99aa | |
parent | 8f5d094db7182cef09fe4ee606e2182bf0e433b5 (diff) | |
download | dbmodel-1772e08823194ee25b3ebf444ef05290b6b33c68.tar.gz dbmodel-1772e08823194ee25b3ebf444ef05290b6b33c68.tar.bz2 |
Add Crow's Foot notation for relationship drawing, disabled by default
-rw-r--r-- | src/items/database/databaserelationship.cpp | 143 | ||||
-rw-r--r-- | src/items/database/databaserelationship.h | 7 |
2 files changed, 118 insertions, 32 deletions
diff --git a/src/items/database/databaserelationship.cpp b/src/items/database/databaserelationship.cpp index 8b4ceda..d908409 100644 --- a/src/items/database/databaserelationship.cpp +++ b/src/items/database/databaserelationship.cpp @@ -29,13 +29,73 @@ public: cardinality(ZeroOrMore), onUpdateAction(NoAction), onDeleteAction(NoAction) - {} + { + if (!pathsInitialized) { + pathsInitialized = true; + + paths[1].moveTo(-4.5, 0); + paths[1].lineTo(0, 8); + paths[1].lineTo(4.5, 0); + paths[1].moveTo(-4, 10); + paths[1].lineTo(4, 10); + + paths[3].moveTo(-4, 5); + paths[3].lineTo(4, 5); + paths[3].moveTo(-4, 8); + paths[3].lineTo(4, 8); + + paths[2].moveTo(-4, 5); + paths[2].lineTo(4, 5); + paths[2].addEllipse(-3.5, 8, 7, 7); + + paths[0].moveTo(-4.5, 0); + paths[0].lineTo(0, 8); + paths[0].lineTo(4.5, 0); + paths[0].addEllipse(-3.5, 8, 7, 7); + + paths[4].moveTo(-4.5, 10); + paths[4].lineTo(0, 0); + paths[4].lineTo(4.5, 10); + } + } Cardinality cardinality; Action onUpdateAction; Action onDeleteAction; + + bool fillEnds; + QPainterPath sourceEnd; + QPainterPath targetEnd; + QPolygonF line; + + QPainterPath crowsFootPath(Cardinality cardinality) + { + switch (cardinality) { + case ZeroOrMore: + return paths[0]; + case OneOrMore: + return paths[1]; + case ZeroOrOne: + return paths[2]; + case One: + return paths[3]; + } + Q_ASSERT(false); + return QPainterPath(); + } + + QPainterPath arrowHeadPath() + { + return paths[4]; + } + + static bool pathsInitialized; + static QPainterPath paths[5]; }; +bool DatabaseRelationship::PrivateData::pathsInitialized = false; +QPainterPath DatabaseRelationship::PrivateData::paths[5]; + DatabaseRelationship::DatabaseRelationship(DiagramItem *parent) : DiagramConnection(parent), d(new PrivateData) { @@ -60,9 +120,17 @@ DatabaseRelationship::setCardinality(Cardinality cardinality) if (d->cardinality != cardinality) { d->cardinality = cardinality; emit propertyChanged("cardinality", cardinality); + updateLayout(); + update(); } } +bool +DatabaseRelationship::isRequired() const +{ + return true; // FIXME +} + QRectF DatabaseRelationship::boundingRect() const { @@ -73,17 +141,18 @@ QPainterPath DatabaseRelationship::shape() const { QPainterPath path; - if (m_line.isEmpty()) + if (d->line.isEmpty()) return path; - path.moveTo(m_line[0]); - for (int i = 1; i < m_line.size(); i++) - path.lineTo(m_line[i]); - path.addPolygon(m_arrowHead); + path.moveTo(d->line[0]); + for (int i = 1; i < d->line.size(); i++) + path.lineTo(d->line[i]); + path.addPath(d->targetEnd); + path.addPath(d->sourceEnd); QPen pen(QPen(QColor(0, 0, 0), 1)); pen.setJoinStyle(Qt::MiterJoin); QPainterPathStroker ps; ps.setCapStyle(pen.capStyle()); - ps.setWidth(pen.widthF() + 0.3); + ps.setWidth(pen.widthF() + 2); ps.setJoinStyle(pen.joinStyle()); ps.setMiterLimit(pen.miterLimit()); return ps.createStroke(path); @@ -104,9 +173,11 @@ DatabaseRelationship::paint(QPainter *painter, const QStyleOptionGraphicsItem *o } painter->setPen(pen); - painter->drawPolyline(m_line); - painter->setBrush(pen.color()); - painter->drawPolygon(m_arrowHead); + painter->drawPolyline(d->line); + if (d->fillEnds) + painter->setBrush(pen.color()); + painter->drawPath(d->sourceEnd); + painter->drawPath(d->targetEnd); } QVariant @@ -156,10 +227,10 @@ DatabaseRelationship::updateLayout() if (!verticalIntersection.isNull() && horizontalIntersection.isNull()) { qreal y = verticalIntersection.min() + verticalIntersection.length() / 2; if (rect1.right() < rect2.left()) { - m_line = QPolygonF() << QPointF(rect1.right(), y) << QPointF(rect2.left(), y); + d->line = QPolygonF() << QPointF(rect1.right(), y) << QPointF(rect2.left(), y); } else { - m_line = QPolygonF() << QPointF(rect1.left(), y) << QPointF(rect2.right(), y); + d->line = QPolygonF() << QPointF(rect1.left(), y) << QPointF(rect2.right(), y); } haveLine = true; } @@ -170,10 +241,10 @@ DatabaseRelationship::updateLayout() if (verticalIntersection.isNull() && !horizontalIntersection.isNull()) { qreal x = horizontalIntersection.min() + horizontalIntersection.length() / 2; if (rect1.bottom() < rect2.top()) { - m_line = QPolygonF() << QPointF(x, rect1.bottom()) << QPointF(x, rect2.top()); + d->line = QPolygonF() << QPointF(x, rect1.bottom()) << QPointF(x, rect2.top()); } else { - m_line = QPolygonF() << QPointF(x, rect1.top()) << QPointF(x, rect2.bottom()); + d->line = QPolygonF() << QPointF(x, rect1.top()) << QPointF(x, rect2.bottom()); } haveLine = true; } @@ -217,7 +288,7 @@ DatabaseRelationship::updateLayout() } } - m_line = QPolygonF() + d->line = QPolygonF() << QPointF(x1, y1) << QPointF(x2, y2) << QPointF(x3, y3); @@ -252,23 +323,41 @@ DatabaseRelationship::updateLayout() } } - m_line = QPolygonF() << finalLine.p1() << finalLine.p2(); + d->line = QPolygonF() << finalLine.p1() << finalLine.p2(); haveLine = true; } Q_ASSERT(haveLine); - int size = m_line.size(); - QLineF lastSegment(m_line[size-2], m_line[size-1]); - - m_arrowHead.resize(3); - m_arrowHead[0] = QPointF(0.0, 0.0); - m_arrowHead[1] = QPointF(-4.5, 10.0); - m_arrowHead[2] = QPointF(4.5, 10.0); - QMatrix matrix; - matrix.rotate(-lastSegment.angle() + 90); - m_arrowHead = matrix.map(m_arrowHead); - m_arrowHead.translate(lastSegment.p2()); + // "Relational" + if (1) { + d->fillEnds = true; + d->targetEnd = d->arrowHeadPath(); + d->sourceEnd = QPainterPath(); + } + // "Crow's Foot" + else { + d->fillEnds = false; + d->targetEnd = d->crowsFootPath(d->cardinality); + d->sourceEnd = d->crowsFootPath(isRequired() ? One : ZeroOrOne); + } + + if (!d->sourceEnd.isEmpty()) { + QLineF firstSegment(d->line[0], d->line[1]); + QMatrix matrix; + matrix.translate(firstSegment.p1().x(), firstSegment.p1().y()); + matrix.rotate(360 - firstSegment.angle() + 90 + 180); + d->sourceEnd = matrix.map(d->sourceEnd); + } + + if (!d->targetEnd.isEmpty()) { + int size = d->line.size(); + QLineF lastSegment(d->line[size-2], d->line[size-1]); + QMatrix matrix; + matrix.translate(lastSegment.p2().x(), lastSegment.p2().y()); + matrix.rotate(-lastSegment.angle() + 90); + d->targetEnd = matrix.map(d->targetEnd); + } } #include "domutils.h" diff --git a/src/items/database/databaserelationship.h b/src/items/database/databaserelationship.h index 4a07e86..d8762cf 100644 --- a/src/items/database/databaserelationship.h +++ b/src/items/database/databaserelationship.h @@ -52,10 +52,10 @@ public: void updatePositions(); //! Returns true if the foreign key on the child table is also the primary key - bool isIdentifying(); + bool isIdentifying() const; //! Returns true if the foreign key on the child table is required (NOT NULL) - bool isRequired(); + bool isRequired() const; enum Cardinality { ZeroOrMore, @@ -99,9 +99,6 @@ protected: private: class PrivateData; PrivateData *const d; - - QPolygonF m_line; - QPolygonF m_arrowHead; }; #endif |