summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukáš Lalinský <lalinsky@gmail.com>2008-12-12 14:41:01 +0100
committerLukáš Lalinský <lalinsky@gmail.com>2008-12-12 14:41:01 +0100
commit1772e08823194ee25b3ebf444ef05290b6b33c68 (patch)
tree79fd31826079ffa150446c26f36cd63200bd99aa
parent8f5d094db7182cef09fe4ee606e2182bf0e433b5 (diff)
downloaddbmodel-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.cpp143
-rw-r--r--src/items/database/databaserelationship.h7
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