summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukáš Lalinský <lalinsky@gmail.com>2009-01-08 23:21:00 +0100
committerLukáš Lalinský <lalinsky@gmail.com>2009-01-08 23:21:00 +0100
commitecc06f131cb73bf9920b52982494846aeeeed345 (patch)
tree166b5dc23665e67c85b51665b144bbc59019822f
parente18ed4667d756977f956c836fce613bbf94c069a (diff)
downloaddbmodel-ecc06f131cb73bf9920b52982494846aeeeed345.tar.gz
dbmodel-ecc06f131cb73bf9920b52982494846aeeeed345.tar.bz2
Move line drawing functionality into the Line class
-rw-r--r--src/diagram/diagram.pri7
-rw-r--r--src/diagram/linelayouter.cpp36
-rw-r--r--src/diagram/linelayouter.h47
-rw-r--r--src/diagramdocument.cpp2
-rw-r--r--src/items/database/databaserelationship.cpp115
-rw-r--r--src/items/database/databaserelationship.h4
-rw-r--r--src/line.cpp197
-rw-r--r--src/line.h34
-rw-r--r--src/src.pro1
9 files changed, 345 insertions, 98 deletions
diff --git a/src/diagram/diagram.pri b/src/diagram/diagram.pri
new file mode 100644
index 0000000..b98b4dd
--- /dev/null
+++ b/src/diagram/diagram.pri
@@ -0,0 +1,7 @@
+DEPENDPATH += $$PWD
+
+SOURCES += \
+ linelayouter.cpp
+
+HEADERS += \
+ linelayouter.h
diff --git a/src/diagram/linelayouter.cpp b/src/diagram/linelayouter.cpp
new file mode 100644
index 0000000..33293a4
--- /dev/null
+++ b/src/diagram/linelayouter.cpp
@@ -0,0 +1,36 @@
+// Copyright (C) 2008 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#include "linelayouter.h"
+
+using namespace Diagram;
+
+LineLayouter::LineLayouter()
+{
+ m_updateTimer = new QTimer(this);
+ m_updateTimer->setSingleShot(true);
+ m_updateTimer->setInterval(5);
+ connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(doUpdate()));
+}
+
+LineLayouter::~LineLayouter()
+{
+}
+
+void
+LineLayouter::doUpdate()
+{
+}
diff --git a/src/diagram/linelayouter.h b/src/diagram/linelayouter.h
new file mode 100644
index 0000000..88fcbef
--- /dev/null
+++ b/src/diagram/linelayouter.h
@@ -0,0 +1,47 @@
+// Copyright (C) 2009 Lukas Lalinsky
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+#ifndef DIAGRAM_LINELAYOUTER_H
+#define DIAGRAM_LINELAYOUTER_H
+
+#include <QObject>
+#include <QTimer>
+
+class Line;
+
+namespace Diagram {
+
+class LineLayouter : public QObject
+{
+ Q_OBJECT
+
+public:
+ LineLayouter();
+ ~LineLayouter();
+
+ void updateLine(Line *line);
+ void addLine(Line *line);
+
+protected slots:
+ void doUpdate();
+
+private:
+ QTimer *m_updateTimer;
+};
+
+}
+
+#endif
diff --git a/src/diagramdocument.cpp b/src/diagramdocument.cpp
index 3c73df6..9e22052 100644
--- a/src/diagramdocument.cpp
+++ b/src/diagramdocument.cpp
@@ -30,6 +30,7 @@
#include <QTextStream>
#include <QStyle>
#include <QSet>
+#include "diagram/linelayouter.h"
using namespace std;
@@ -57,6 +58,7 @@ public:
QSet<Line *> linesToUpdate;
QSet<DiagramObject *> objectsToUpdate;
QMap<QString, int> counters;
+ Diagram::LineLayouter *lineLayouter;
};
DiagramDocument::DiagramDocument(QObject *parent)
diff --git a/src/items/database/databaserelationship.cpp b/src/items/database/databaserelationship.cpp
index aacacf6..c1cddce 100644
--- a/src/items/database/databaserelationship.cpp
+++ b/src/items/database/databaserelationship.cpp
@@ -62,9 +62,10 @@ public:
paths[0].lineTo(5, 0);
paths[0].addEllipse(-3.5, 8, 7, 7);
- paths[4].moveTo(-4.5, 10);
+ paths[4].moveTo(-4.5, 9);
paths[4].lineTo(0, 0);
- paths[4].lineTo(4.5, 10);
+ paths[4].lineTo(4.5, 9);
+ paths[4].lineTo(-4.5, 9);
}
}
@@ -76,12 +77,6 @@ public:
Column *childColumn;
Column *parentColumn;
- bool fillEnds;
- QPainterPath sourceEnd;
- QPainterPath targetEnd;
- QPolygonF line;
- Qt::PenStyle lineStyle;
-
QPainterPath crowsFootPath(bool toMany, bool optional)
{
if (toMany) {
@@ -220,59 +215,6 @@ DatabaseRelationship::isIdentifying() const
return false;
}
-QRectF
-DatabaseRelationship::boundingRect() const
-{
- return shape().controlPointRect();
-}
-
-QPainterPath
-DatabaseRelationship::shape() const
-{
- QPainterPath path;
- if (d->line.isEmpty())
- return path;
- 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.33));
- pen.setJoinStyle(Qt::MiterJoin);
- QPainterPathStroker ps;
- ps.setCapStyle(pen.capStyle());
- ps.setWidth(pen.widthF() + 2);
- ps.setJoinStyle(pen.joinStyle());
- ps.setMiterLimit(pen.miterLimit());
- return ps.createStroke(path);
-}
-
-void
-DatabaseRelationship::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
-{
- Q_UNUSED(option);
- Q_UNUSED(widget);
-
- QPen pen(QPen(QColor(0, 0, 0), 1.5));
- pen.setJoinStyle(Qt::MiterJoin);
- pen.setStyle(d->lineStyle);
-
- if (!document()->isPrinting() && isSelected()) {
- pen.setColor(QColor(0, 96, 255));
-// pen.setWidth(2);
- }
-
- painter->setPen(pen);
- painter->drawPolyline(d->line);
- if (d->fillEnds)
- painter->setBrush(pen.color());
-
- pen.setStyle(Qt::SolidLine);
- painter->setPen(pen);
- painter->drawPath(d->sourceEnd);
- painter->drawPath(d->targetEnd);
-}
-
QVariant
DatabaseRelationship::itemChange(GraphicsItemChange change, const QVariant &value)
{
@@ -290,35 +232,20 @@ DatabaseRelationship::updateEnds()
switch (document()->notation()) {
case DiagramDocument::Relational:
- d->fillEnds = true;
- d->targetEnd = d->arrowHeadPath();
- d->sourceEnd = QPainterPath();
- d->lineStyle = Qt::SolidLine;
+ setFillStartArrow(false);
+ setFillEndArrow(true);
+ setStartArrow(QPainterPath());
+ setEndArrow(d->arrowHeadPath());
+ setLineStyle(Qt::SolidLine);
break;
case DiagramDocument::CrowsFoot:
- d->fillEnds = false;
- d->targetEnd = d->crowsFootPath(d->cardinality == ManyToMany, isParentOptional());
- d->sourceEnd = d->crowsFootPath(d->cardinality != OneToOne, isChildOptional());
- d->lineStyle = isIdentifying() ? Qt::SolidLine : Qt::DashLine;
+ setFillStartArrow(false);
+ setFillEndArrow(false);
+ setStartArrow(d->crowsFootPath(d->cardinality != OneToOne, isChildOptional()));
+ setEndArrow(d->crowsFootPath(d->cardinality == ManyToMany, isParentOptional()));
+ setLineStyle(isIdentifying() ? Qt::SolidLine : Qt::DashLine);
break;
}
-
- 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);
- }
}
void
@@ -331,6 +258,8 @@ DatabaseRelationship::updateLayout()
bool haveLine = false;
+ QPolygonF line;
+
// Orthogonal line
if (!haveLine) {
QPointF p1 = connector1->pos();
@@ -341,24 +270,23 @@ DatabaseRelationship::updateLayout()
QLineF line1 = QLineF::fromPolar(1, a1).translated(p1);
QLineF line2 = QLineF::fromPolar(1, a2).translated(p2);
QPointF intersection;
- d->line.clear();
- d->line << p1;
+ line << p1;
if (line1.intersect(line2, &intersection) != QLineF::NoIntersection) {
// 2-segment line
- d->line << intersection;
+ line << intersection;
}
else {
if (line1.intersect(line2.normalVector(), &intersection) != QLineF::NoIntersection) {
// 3-segment line
qreal len = QLineF(p1, intersection).length() * 0.5;
- d->line << QLineF::fromPolar(len, a1).translated(p1).p2();
- d->line << QLineF::fromPolar(len, a2).translated(p2).p2();
+ line << QLineF::fromPolar(len, a1).translated(p1).p2();
+ line << QLineF::fromPolar(len, a2).translated(p2).p2();
}
else {
qFatal("No line?");
}
}
- d->line << p2;
+ line << p2;
haveLine = true;
}
@@ -366,10 +294,11 @@ DatabaseRelationship::updateLayout()
if (!haveLine) {
QPointF p1 = connector1->pos();
QPointF p2 = connector2->pos();
- d->line = QPolygonF() << p1 << p2;
+ line << p1 << p2;
haveLine = true;
}
+ setLinePoints(line);
updateEnds();
}
diff --git a/src/items/database/databaserelationship.h b/src/items/database/databaserelationship.h
index 044a891..7fe6f61 100644
--- a/src/items/database/databaserelationship.h
+++ b/src/items/database/databaserelationship.h
@@ -38,10 +38,6 @@ public:
DatabaseRelationship(DiagramItem *parent = 0);
~DatabaseRelationship();
- QRectF boundingRect() const;
- QPainterPath shape() const;
- void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
-
DatabaseTable *childTable() const { return qobject_cast<DatabaseTable *>(connector(0)->connectedObject()); }
DatabaseTable *parentTable() const { return qobject_cast<DatabaseTable *>(connector(1)->connectedObject()); }
diff --git a/src/line.cpp b/src/line.cpp
index 133c02f..527fab3 100644
--- a/src/line.cpp
+++ b/src/line.cpp
@@ -14,6 +14,7 @@
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#include <QPainter>
#include "line.h"
#include "hub.h"
#include "diagramdocument.h"
@@ -21,7 +22,7 @@
#include "connector.h"
Line::Line(DiagramItem *parent)
- : DiagramItem(parent)
+ : DiagramItem(parent), m_fillStartArrow(false), m_fillEndArrow(false), m_dirty(false)
{
m_connectors[0] = new Connector(this);
m_connectors[1] = new Connector(this);
@@ -97,3 +98,197 @@ Line::saveToXml(QDomDocument doc, QDomElement element)
}
}
}
+
+QPolygonF
+Line::linePoints() const
+{
+ return m_linePoints;
+}
+
+void
+Line::setLinePoints(const QPolygonF& points)
+{
+ if (m_linePoints != points) {
+ prepareGeometryChange();
+ m_linePoints = points;
+ m_dirty = true;
+ }
+}
+
+Qt::PenStyle
+Line::lineStyle() const
+{
+ return m_lineStyle;
+}
+
+void
+Line::setLineStyle(Qt::PenStyle style)
+{
+ if (m_lineStyle != style) {
+ // prepareGeometryChange();
+ m_lineStyle = style;
+ // m_dirty = true;
+ }
+}
+
+QPainterPath
+Line::startArrow() const
+{
+ return m_startArrow;
+}
+
+void
+Line::setStartArrow(const QPainterPath& path)
+{
+ if (m_startArrow != path) {
+ prepareGeometryChange();
+ m_startArrow = path;
+ m_dirty = true;
+ }
+}
+
+bool
+Line::fillStartArrow() const
+{
+ return m_fillStartArrow;
+}
+
+void
+Line::setFillStartArrow(bool fill)
+{
+ if (m_fillStartArrow != fill) {
+ m_fillStartArrow = fill;
+ m_dirty = true;
+ }
+}
+
+QPainterPath
+Line::endArrow() const
+{
+ return m_endArrow;
+}
+
+void
+Line::setEndArrow(const QPainterPath& path)
+{
+ if (m_endArrow != path) {
+ prepareGeometryChange();
+ m_endArrow = path;
+ m_dirty = true;
+ }
+}
+
+bool
+Line::fillEndArrow() const
+{
+ return m_fillEndArrow;
+}
+
+void
+Line::setFillEndArrow(bool fill)
+{
+ if (m_fillEndArrow != fill) {
+ m_fillEndArrow = fill;
+ m_dirty = true;
+ }
+}
+
+void
+Line::updateCache()
+{
+ m_dirty = false;
+
+ QPainterPath path;
+ if (m_linePoints.isEmpty()) {
+ // Nothing to process
+ m_shape = path;
+ return;
+ }
+
+ if (!m_startArrow.isEmpty()) {
+ QLineF firstSegment(m_linePoints.at(0), m_linePoints.at(1));
+ QMatrix matrix;
+ matrix.translate(firstSegment.p1().x(), firstSegment.p1().y());
+ matrix.rotate(360 - firstSegment.angle() + 90 + 180);
+ m_transformedStartArrow = matrix.map(m_startArrow);
+ }
+ else {
+ m_transformedStartArrow = QPainterPath();
+ }
+
+ if (!m_endArrow.isEmpty()) {
+ int size = m_linePoints.size();
+ QLineF lastSegment(m_linePoints.at(size-2), m_linePoints.at(size-1));
+ QMatrix matrix;
+ matrix.translate(lastSegment.p2().x(), lastSegment.p2().y());
+ matrix.rotate(-lastSegment.angle() + 90);
+ m_transformedEndArrow = matrix.map(m_endArrow);
+ }
+ else {
+ m_transformedEndArrow = QPainterPath();
+ }
+
+ // Add the main line
+ path.moveTo(m_linePoints.at(0));
+ for (int i = 1; i < m_linePoints.size(); i++)
+ path.lineTo(m_linePoints.at(i));
+
+ path.addPath(m_transformedStartArrow);
+ path.addPath(m_transformedEndArrow);
+
+ // Add an outline around the path
+ QPainterPathStroker ps;
+ ps.setWidth(4.33);
+ ps.setJoinStyle(Qt::MiterJoin);
+ m_shape = ps.createStroke(path);
+}
+
+QRectF
+Line::boundingRect() const
+{
+ return shape().controlPointRect();
+}
+
+QPainterPath
+Line::shape() const
+{
+ if (m_dirty)
+ const_cast<Line *>(this)->updateCache();
+
+ return m_shape;
+}
+
+void
+Line::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+{
+ if (m_dirty)
+ updateCache();
+
+ QPen pen(QPen(QColor(0, 0, 0), 1.33));
+ pen.setJoinStyle(Qt::MiterJoin);
+ pen.setStyle(m_lineStyle);
+ if (!document()->isPrinting() && isSelected()) {
+ pen.setColor(QColor(0, 96, 255));
+ }
+
+ painter->setPen(pen);
+ painter->drawPolyline(m_linePoints);
+
+ pen.setStyle(Qt::SolidLine);
+ painter->setPen(pen);
+ if (m_fillStartArrow) {
+ painter->setBrush(pen.color());
+ }
+ painter->drawPath(m_transformedStartArrow);
+ if (m_fillEndArrow) {
+ if (!m_fillStartArrow) {
+ painter->setBrush(pen.color());
+ }
+ }
+ else {
+ if (m_fillStartArrow) {
+ painter->setBrush(QBrush());
+ }
+ }
+ painter->drawPath(m_transformedEndArrow);
+}
diff --git a/src/line.h b/src/line.h
index 79de959..a79abe4 100644
--- a/src/line.h
+++ b/src/line.h
@@ -38,13 +38,47 @@ public:
Connector *connector(int index) const;
+ QRectF boundingRect() const;
+ QPainterPath shape() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
virtual void updateLayout();
virtual void loadFromXml(QDomElement element, DiagramDocument *document = 0);
void saveToXml(QDomDocument doc, QDomElement element);
+ QPolygonF linePoints() const;
+ void setLinePoints(const QPolygonF &points);
+
+ Qt::PenStyle lineStyle() const;
+ void setLineStyle(Qt::PenStyle style);
+
+ QPainterPath startArrow() const;
+ void setStartArrow(const QPainterPath &path);
+
+ bool fillStartArrow() const;
+ void setFillStartArrow(bool fill);
+
+ QPainterPath endArrow() const;
+ void setEndArrow(const QPainterPath &path);
+
+ bool fillEndArrow() const;
+ void setFillEndArrow(bool fill);
+
private:
+ void updateCache();
+
Connector *m_connectors[2];
+ QPolygonF m_linePoints;
+ Qt::PenStyle m_lineStyle;
+ QPainterPath m_shape;
+ QPainterPath m_startArrow;
+ QPainterPath m_transformedStartArrow;
+ bool m_fillStartArrow;
+ QPainterPath m_endArrow;
+ QPainterPath m_transformedEndArrow;
+ bool m_fillEndArrow;
+ bool m_dirty;
};
#endif
diff --git a/src/src.pro b/src/src.pro
index 526656d..91cedb2 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -5,6 +5,7 @@ QT += xml svg
CONFIG += debug
include(src.pri)
+include(diagram/diagram.pri)
include(items/items.pri)
include(utils/utils.pri)