summaryrefslogtreecommitdiff
path: root/src/data
diff options
context:
space:
mode:
Diffstat (limited to 'src/data')
-rw-r--r--src/data/edge.cpp11
-rw-r--r--src/data/edge.h8
-rw-r--r--src/data/graph.cpp154
-rw-r--r--src/data/graph.h5
-rw-r--r--src/data/graphelementdata.cpp35
-rw-r--r--src/data/graphelementdata.h5
-rw-r--r--src/data/path.cpp35
-rw-r--r--src/data/path.h25
-rw-r--r--src/data/style.cpp75
-rw-r--r--src/data/style.h11
-rw-r--r--src/data/tikzassembler.cpp71
-rw-r--r--src/data/tikzassembler.h19
-rw-r--r--src/data/tikzdocument.cpp1
-rw-r--r--src/data/tikzlexer.l1
-rw-r--r--src/data/tikzparser.y85
-rw-r--r--src/data/tikzparserdefs.h2
16 files changed, 455 insertions, 88 deletions
diff --git a/src/data/edge.cpp b/src/data/edge.cpp
index 0bd49e8..652b480 100644
--- a/src/data/edge.cpp
+++ b/src/data/edge.cpp
@@ -28,6 +28,7 @@ Edge::Edge(Node *s, Node *t, QObject *parent) :
{
_data = new GraphElementData(this);
_edgeNode = nullptr;
+ _path = nullptr;
_dirty = true;
if (s != t) {
@@ -436,3 +437,13 @@ QPointF Edge::bezierTangent(qreal start, qreal end) const
return QPointF(dx, dy);
}
+
+Path *Edge::path() const
+{
+ return _path;
+}
+
+void Edge::setPath(Path *path)
+{
+ _path = path;
+}
diff --git a/src/data/edge.h b/src/data/edge.h
index 954145f..ad21f36 100644
--- a/src/data/edge.h
+++ b/src/data/edge.h
@@ -27,6 +27,8 @@
#include "node.h"
#include "style.h"
+class Path;
+
#include <QObject>
#include <QPointF>
@@ -92,12 +94,15 @@ public:
void setStyleName(const QString & styleName);
Style *style() const;
+ Path *path() const;
+ void setPath(Path *path);
+
signals:
public slots:
private:
- QPointF bezierTangent(qreal start, qreal end) const;
+ QPointF bezierTangent(qreal start, qreal end) const;
QString _sourceAnchor;
QString _targetAnchor;
@@ -108,6 +113,7 @@ private:
// referenced
Node *_source;
Node *_target;
+ Path *_path;
Style *_style;
diff --git a/src/data/graph.cpp b/src/data/graph.cpp
index 1dd5574..74de24d 100644
--- a/src/data/graph.cpp
+++ b/src/data/graph.cpp
@@ -73,6 +73,17 @@ void Graph::removeEdge(Edge *e)
_edges.removeOne(e);
}
+void Graph::addPath(Path *p)
+{
+ p->setParent(this);
+ _paths << p;
+}
+
+void Graph::removePath(Path *p)
+{
+ _paths.removeOne(p);
+}
+
int Graph::maxIntName()
{
int max = -1;
@@ -167,6 +178,11 @@ const QVector<Edge*> &Graph::edges()
return _edges;
}
+const QVector<Path *> &Graph::paths()
+{
+ return _paths;
+}
+
QRectF Graph::bbox() const
{
return _bbox;
@@ -230,37 +246,93 @@ QString Graph::tikz()
Edge *e;
+ Path *p;
foreach (e, _edges) {
- e->setTikzLine(line);
- e->updateData();
- code << "\t\t\\draw ";
-
- if (!e->data()->isEmpty())
- code << e->data()->tikz() << " ";
-
- code << "(" << e->source()->name();
- if (e->sourceAnchor() != "")
- code << "." << e->sourceAnchor();
- code << ") to ";
-
- if (e->hasEdgeNode()) {
- code << "node ";
- if (!e->edgeNode()->data()->isEmpty())
- code << e->edgeNode()->data()->tikz() << " ";
- code << "{" << e->edgeNode()->label() << "} ";
- }
+ p = e->path();
+ if (p) { // if edge is part of a path
+ if (p->edges().first() == e) { // only add tikz code once per path
+ e->setTikzLine(line);
+ e->updateData();
+ code << "\t\t\\draw ";
+
+ GraphElementData *npd = e->data()->nonPathData();
+ if (!npd->isEmpty())
+ code << npd->tikz() << " ";
+ delete npd;
+
+ code << "(" << e->source()->name();
+ if (e->sourceAnchor() != "") {
+ code << "." << e->sourceAnchor();
+ } else if (p->isCycle()) {
+ code << ".center";
+ }
+ code << ")";
+
+ foreach (Edge *e1, p->edges()) {
+ code << "\n\t\t\t to ";
+ line++;
+ e1->setTikzLine(line);
+ e1->updateData();
+
+ GraphElementData *pd = e1->data()->pathData();
+ if (!pd->isEmpty())
+ code << pd->tikz() << " ";
+ delete pd;
+
+ if (e1->hasEdgeNode()) {
+ code << "node ";
+ if (!e1->edgeNode()->data()->isEmpty())
+ code << e1->edgeNode()->data()->tikz() << " ";
+ code << "{" << e1->edgeNode()->label() << "} ";
+ }
+
+ if (e->source() == e1->target()) {
+ code << "cycle";
+ } else {
+ code << "(" << e1->target()->name();
+ if (e1->targetAnchor() != "") {
+ code << "." << e1->targetAnchor();
+ } else if (e1 != p->edges().last()) {
+ code << ".center";
+ }
+ code << ")";
+ }
+ }
+ code << ";\n";
+ line++;
+ }
+ } else { // edge is not part of a path
+ e->setTikzLine(line);
+ e->updateData();
+ code << "\t\t\\draw ";
+
+ if (!e->data()->isEmpty())
+ code << e->data()->tikz() << " ";
+
+ code << "(" << e->source()->name();
+ if (e->sourceAnchor() != "")
+ code << "." << e->sourceAnchor();
+ code << ") to ";
+
+ if (e->hasEdgeNode()) {
+ code << "node ";
+ if (!e->edgeNode()->data()->isEmpty())
+ code << e->edgeNode()->data()->tikz() << " ";
+ code << "{" << e->edgeNode()->label() << "} ";
+ }
- if (e->source() == e->target()) {
- code << "()";
- } else {
- code << "(" << e->target()->name();
- if (e->targetAnchor() != "")
- code << "." << e->targetAnchor();
- code << ")";
- }
+ if (e->source() == e->target()) {
+ code << "()";
+ } else {
+ code << "(" << e->target()->name();
+ if (e->targetAnchor() != "")
+ code << "." << e->targetAnchor();
+ code << ")";
+ }
- code << ";\n";
- line++;
+ code << ";\n";
+ line++;
+ }
}
if (!_edges.isEmpty()) {
@@ -288,9 +360,33 @@ Graph *Graph::copyOfSubgraphWithNodes(QSet<Node *> nds)
g->addNode(n1);
}
}
+
+ QMap<Edge*,Edge*> edgeTable;
foreach (Edge *e, edges()) {
if (nds.contains(e->source()) && nds.contains(e->target())) {
- g->addEdge(e->copy(&nodeTable));
+ Edge *e1 = e->copy(&nodeTable);
+ g->addEdge(e1);
+ edgeTable.insert(e,e1);
+ }
+ }
+
+ // add a copy of a path to the new graph if all of the edges are there
+ foreach (Path *p, paths()) {
+ bool allEdges = true;
+ Path *p1 = new Path();
+ foreach (Edge *e1, p->edges()) {
+ if (edgeTable.contains(e1)) {
+ p1->addEdge(edgeTable[e1]);
+ } else {
+ allEdges = false;
+ break;
+ }
+ }
+ if (allEdges) {
+ g->addPath(p1);
+ } else {
+ p1->removeEdges();
+ delete p1;
}
}
diff --git a/src/data/graph.h b/src/data/graph.h
index 286ccdc..c306bb2 100644
--- a/src/data/graph.h
+++ b/src/data/graph.h
@@ -25,6 +25,7 @@
#include "node.h"
#include "edge.h"
+#include "path.h"
#include "graphelementdata.h"
#include <QObject>
@@ -46,6 +47,8 @@ public:
void addEdge(Edge *e);
void addEdge(Edge *e, int index);
void removeEdge(Edge *e);
+ void addPath(Path *p);
+ void removePath(Path *p);
int maxIntName();
void reorderNodes(const QVector<Node*> &newOrder);
void reorderEdges(const QVector<Edge*> &newOrder);
@@ -64,6 +67,7 @@ public:
const QVector<Node *> &nodes();
const QVector<Edge*> &edges();
+ const QVector<Path*> &paths();
QRectF bbox() const;
void setBbox(const QRectF &bbox);
@@ -121,6 +125,7 @@ public slots:
private:
QVector<Node*> _nodes;
QVector<Edge*> _edges;
+ QVector<Path*> _paths;
//QMultiHash<Node*,Edge*> inEdges;
//QMultiHash<Node*,Edge*> outEdges;
GraphElementData *_data;
diff --git a/src/data/graphelementdata.cpp b/src/data/graphelementdata.cpp
index cd09a6d..e1e89b1 100644
--- a/src/data/graphelementdata.cpp
+++ b/src/data/graphelementdata.cpp
@@ -110,6 +110,14 @@ int GraphElementData::indexOfKey(QString key)
return -1;
}
+void GraphElementData::mergeData(GraphElementData *d)
+{
+ GraphElementProperty p;
+ foreach (p, d->properties()) {
+ if (!hasProperty(p.key())) add(p);
+ }
+}
+
bool GraphElementData::removeRows(int row, int /*count*/, const QModelIndex &parent)
{
if (row >= 0 && row < _properties.length()) {
@@ -257,3 +265,30 @@ QVector<GraphElementProperty> GraphElementData::properties() const
{
return _properties;
}
+
+GraphElementData *GraphElementData::pathData() const
+{
+ GraphElementData *d = new GraphElementData();
+ foreach(GraphElementProperty p, _properties) {
+ if (isPathProperty(p.key())) d->add(p);
+ }
+ return d;
+}
+
+GraphElementData *GraphElementData::nonPathData() const
+{
+ GraphElementData *d = new GraphElementData();
+ foreach(GraphElementProperty p, _properties) {
+ if (!isPathProperty(p.key())) d->add(p);
+ }
+ return d;
+}
+
+bool GraphElementData::isPathProperty(QString key)
+{
+ return (key == "bend left" ||
+ key == "bend right" ||
+ key == "in" ||
+ key == "out" ||
+ key == "looseness");
+}
diff --git a/src/data/graphelementdata.h b/src/data/graphelementdata.h
index dce0d46..8022a14 100644
--- a/src/data/graphelementdata.h
+++ b/src/data/graphelementdata.h
@@ -49,6 +49,7 @@ public:
bool hasProperty(QString key);
bool atom(QString atom);
int indexOfKey(QString key);
+ void mergeData(GraphElementData *d);
bool removeRows(int row, int count, const QModelIndex &parent) override;
bool moveRows(const QModelIndex &sourceParent,
int sourceRow, int,
@@ -77,12 +78,16 @@ public:
bool isEmpty();
QVector<GraphElementProperty> properties() const;
+ GraphElementData *pathData() const;
+ GraphElementData *nonPathData() const;
+
signals:
public slots:
private:
QVector<GraphElementProperty> _properties;
+ static bool isPathProperty(QString key);
};
#endif // GRAPHELEMENTDATA_H
diff --git a/src/data/path.cpp b/src/data/path.cpp
new file mode 100644
index 0000000..1438d64
--- /dev/null
+++ b/src/data/path.cpp
@@ -0,0 +1,35 @@
+#include "path.h"
+
+Path::Path(QObject *parent) : QObject(parent)
+{
+
+}
+
+int Path::length() const
+{
+ return _edges.length();
+}
+
+void Path::addEdge(Edge *e)
+{
+ e->setPath(this);
+ _edges << e;
+}
+
+void Path::removeEdges()
+{
+ foreach(Edge *e, _edges) {
+ e->setPath(nullptr);
+ }
+ _edges.clear();
+}
+
+bool Path::isCycle() const
+{
+ return !_edges.isEmpty() && _edges.first()->source() == _edges.last()->target();
+}
+
+QVector<Edge *> Path::edges() const
+{
+ return _edges;
+}
diff --git a/src/data/path.h b/src/data/path.h
new file mode 100644
index 0000000..3c83170
--- /dev/null
+++ b/src/data/path.h
@@ -0,0 +1,25 @@
+#ifndef PATH_H
+#define PATH_H
+
+#include "edge.h"
+
+#include <QObject>
+
+class Path : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Path(QObject *parent = nullptr);
+ int length() const;
+ void addEdge(Edge *e);
+ void removeEdges();
+ bool isCycle() const;
+
+ QVector<Edge *> edges() const;
+
+private:
+ QVector<Edge*> _edges;
+
+};
+
+#endif // PATH_H
diff --git a/src/data/style.cpp b/src/data/style.cpp
index d0f011d..f4aa892 100644
--- a/src/data/style.cpp
+++ b/src/data/style.cpp
@@ -62,7 +62,22 @@ QColor Style::fillColor(bool tikzitOverride) const
QBrush Style::brush() const
{
- return QBrush(fillColor());
+ if (hasFill()) {
+ return QBrush(fillColor());
+ } else {
+ return Qt::NoBrush;
+ }
+}
+
+bool Style::hasFill() const
+{
+ return (propertyWithDefault("fill", "none") != "none");
+}
+
+bool Style::hasStroke() const
+{
+ if (isEdgeStyle()) return propertyWithDefault("draw", "black") != "none";
+ else return (propertyWithDefault("draw", "none") != "none");
}
QString Style::shape(bool tikzitOverride) const
@@ -152,24 +167,28 @@ Style::DrawStyle Style::drawStyle() const
QPen Style::pen() const
{
- QPen p(strokeColor());
- p.setWidthF((float)strokeThickness() * 2.0f);
-
- QVector<qreal> pat;
- switch (drawStyle()) {
- case Dashed:
- pat << 3.0 << 3.0;
- p.setDashPattern(pat);
- break;
- case Dotted:
- pat << 1.0 << 1.0;
- p.setDashPattern(pat);
- break;
- case Solid:
- break;
- }
+ if (hasStroke()) {
+ QPen p(strokeColor());
+ p.setWidthF((float)strokeThickness() * 2.0f);
+
+ QVector<qreal> pat;
+ switch (drawStyle()) {
+ case Dashed:
+ pat << 3.0 << 3.0;
+ p.setDashPattern(pat);
+ break;
+ case Dotted:
+ pat << 1.0 << 1.0;
+ p.setDashPattern(pat);
+ break;
+ case Solid:
+ break;
+ }
- return p;
+ return p;
+ } else {
+ return Qt::NoPen;
+ }
}
QPainterPath Style::path() const
@@ -225,19 +244,27 @@ QIcon Style::icon() const
px.fill(Qt::transparent);
QPainter painter(&px);
- if (_data == 0) {
- QPen pen(Qt::black);
- pen.setWidth(3);
- } else {
- painter.setPen(pen());
+// if (_data == 0) {
+// QPen pen(Qt::black);
+// pen.setWidth(3);
+// } else {
+// painter.setPen(pen());
+// }
+
+ QPen pn = pen();
+ painter.setPen(pn);
+
+ if (hasFill()) {
+ painter.fillRect(10,50,80,30,brush());
}
painter.drawLine(10, 50, 90, 50);
- QPen pn = pen();
pn.setStyle(Qt::SolidLine);
painter.setPen(pn);
+
+
switch (arrowHead()) {
case Pointer:
painter.drawLine(90,50,80,40);
diff --git a/src/data/style.h b/src/data/style.h
index 78e11dc..0e795e1 100644
--- a/src/data/style.h
+++ b/src/data/style.h
@@ -57,18 +57,21 @@ public:
void setName(const QString &name);
QString propertyWithDefault(QString prop, QString def, bool tikzitOverride=true) const;
QString tikz() const;
- void setArrowAtom(QString atom);
-
- // only relevant for node styles
QColor fillColor(bool tikzitOverride=true) const;
QBrush brush() const;
+ bool hasFill() const;
+ bool hasStroke() const;
+
+ // only relevant for node styles
QString shape(bool tikzitOverride=true) const;
+ QString category() const;
// only relevant for edge styles
Style::ArrowTipStyle arrowHead() const;
Style::ArrowTipStyle arrowTail() const;
Style::DrawStyle drawStyle() const;
- QString category() const;
+ void setArrowAtom(QString atom);
+
protected:
QString _name;
diff --git a/src/data/tikzassembler.cpp b/src/data/tikzassembler.cpp
index cd0b517..3cb3c10 100644
--- a/src/data/tikzassembler.cpp
+++ b/src/data/tikzassembler.cpp
@@ -29,6 +29,8 @@ TikzAssembler::TikzAssembler(Graph *graph, QObject *parent) :
{
yylex_init(&scanner);
yyset_extra(this, scanner);
+ _currentEdgeData = nullptr;
+ _currentPath = nullptr;
}
TikzAssembler::TikzAssembler(TikzStyles *tikzStyles, QObject *parent) :
@@ -36,6 +38,8 @@ TikzAssembler::TikzAssembler(TikzStyles *tikzStyles, QObject *parent) :
{
yylex_init(&scanner);
yyset_extra(this, scanner);
+ _currentEdgeData = nullptr;
+ _currentPath = nullptr;
}
void TikzAssembler::addNodeToMap(Node *n) { _nodeMap.insert(n->name(), n); }
@@ -70,3 +74,70 @@ bool TikzAssembler::isTikzStyles() const
return _tikzStyles != 0;
}
+Node *TikzAssembler::currentEdgeSource() const
+{
+ return _currentEdgeSource;
+}
+
+void TikzAssembler::setCurrentEdgeSource(Node *currentEdgeSource)
+{
+ _currentEdgeSource = currentEdgeSource;
+}
+
+Node *TikzAssembler::currentPathSource() const
+{
+ if (_currentPath && _currentPath->length() > 0) {
+ return _currentPath->edges()[0]->source();
+ } else {
+ return nullptr;
+ }
+}
+
+GraphElementData *TikzAssembler::currentEdgeData() const
+{
+ return _currentEdgeData;
+}
+
+void TikzAssembler::setCurrentEdgeData(GraphElementData *currentEdgeData)
+{
+ _currentEdgeData = currentEdgeData;
+}
+
+QString TikzAssembler::currentEdgeSourceAnchor() const
+{
+ return _currentEdgeSourceAnchor;
+}
+
+void TikzAssembler::setCurrentEdgeSourceAnchor(const QString &currentEdgeSourceAnchor)
+{
+ _currentEdgeSourceAnchor = currentEdgeSourceAnchor;
+}
+
+void TikzAssembler::addEdge(Edge *e)
+{
+ if (!_currentPath) _currentPath = new Path();
+ _currentPath->addEdge(e);
+ _graph->addEdge(e);
+}
+
+void TikzAssembler::finishCurrentPath()
+{
+ if (_currentEdgeData) {
+ GraphElementData *d = _currentEdgeData;
+ _currentEdgeData = nullptr;
+ delete d;
+ }
+
+ if (_currentPath) {
+ if (_currentPath->length() < 2) {
+ _currentPath->removeEdges();
+ Path *p = _currentPath;
+ _currentPath = nullptr;
+ delete p;
+ } else {
+ _graph->addPath(_currentPath);
+ _currentPath = nullptr;
+ }
+ }
+}
+
diff --git a/src/data/tikzassembler.h b/src/data/tikzassembler.h
index 7b32224..f86abcd 100644
--- a/src/data/tikzassembler.h
+++ b/src/data/tikzassembler.h
@@ -23,7 +23,6 @@
#ifndef TIKZASSEMBLER_H
#define TIKZASSEMBLER_H
-#include "node.h"
#include "graph.h"
#include "tikzstyles.h"
@@ -46,6 +45,20 @@ public:
bool isTikzStyles() const;
+ Node *currentEdgeSource() const;
+ void setCurrentEdgeSource(Node *currentEdgeSource);
+
+ Node *currentPathSource() const;
+
+ GraphElementData *currentEdgeData() const;
+ void setCurrentEdgeData(GraphElementData *currentEdgeData);
+
+ QString currentEdgeSourceAnchor() const;
+ void setCurrentEdgeSourceAnchor(const QString &currentEdgeSourceAnchor);
+
+ void addEdge(Edge *e);
+ void finishCurrentPath();
+
signals:
public slots:
@@ -54,6 +67,10 @@ private:
QHash<QString,Node*> _nodeMap;
Graph *_graph;
TikzStyles *_tikzStyles;
+ Path *_currentPath;
+ Node *_currentEdgeSource;
+ GraphElementData *_currentEdgeData;
+ QString _currentEdgeSourceAnchor;
void *scanner;
};
diff --git a/src/data/tikzdocument.cpp b/src/data/tikzdocument.cpp
index 1099779..633242d 100644
--- a/src/data/tikzdocument.cpp
+++ b/src/data/tikzdocument.cpp
@@ -90,6 +90,7 @@ void TikzDocument::open(QString fileName)
refreshTikz();
setClean();
} else {
+ // TODO: should not quietly fail to open
newGraph->deleteLater();
_parseSuccess = false;
}
diff --git a/src/data/tikzlexer.l b/src/data/tikzlexer.l
index 0d80467..615cf0d 100644
--- a/src/data/tikzlexer.l
+++ b/src/data/tikzlexer.l
@@ -82,6 +82,7 @@ FLOAT \-?[0-9]*(\.[0-9]+)?
<INITIAL>node { return NODE; }
<INITIAL>at { return AT; }
<INITIAL>to { return TO; }
+<INITIAL>cycle { return CYCLE; }
\([ ]*{FLOAT}[ ]*,[ ]*{FLOAT}[ ]*\) {
yylloc->last_column = yylloc->first_column + 1;
diff --git a/src/data/tikzparser.y b/src/data/tikzparser.y
index 4473107..678d8bf 100644
--- a/src/data/tikzparser.y
+++ b/src/data/tikzparser.y
@@ -96,6 +96,7 @@ void yyerror(YYLTYPE *yylloc, void * /*scanner*/, const char *str) {
%token NODE "node"
%token AT "at"
%token TO "to"
+%token CYCLE "cycle"
%token SEMICOLON ";"
%token COMMA ","
@@ -214,10 +215,13 @@ noderef: "(" REFSTRING optanchor ")"
$$.node = assembler->nodeWithName(QString($2));
free($2);
$$.anchor = $3;
+ $$.loop = false;
+ $$.cycle = false;
};
optnoderef:
- noderef { $$ = $1; }
- | "(" ")" { $$.node = 0; $$.anchor = 0; }
+ noderef { $$ = $1; }
+ | "(" ")" { $$.node = 0; $$.anchor = 0; $$.loop = true; $$.cycle = false; }
+ | "cycle" { $$.node = 0; $$.anchor = 0; $$.loop = false; $$.cycle = true; }
optedgenode:
{ $$ = 0; }
| "node" optproperties DELIMITEDSTRING
@@ -228,45 +232,68 @@ optedgenode:
$$->setLabel(QString($3));
free($3);
}
-edge: "\\draw" optproperties noderef "to" optedgenode optnoderef ";"
- {
- Node *s;
+
+edgesource: optproperties noderef {
+ assembler->setCurrentEdgeSource($2.node);
+ if ($2.anchor) {
+ assembler->setCurrentEdgeSourceAnchor(QString($2.anchor));
+ free($2.anchor);
+ } else {
+ assembler->setCurrentEdgeSourceAnchor(QString());
+ }
+ assembler->setCurrentEdgeData($1);
+ }
+
+optedgetargets: edgetarget optedgetargets |
+
+edgetarget: "to" optproperties optedgenode optnoderef {
+ Node *s = assembler->currentEdgeSource();;
Node *t;
-
- s = $3.node;
- if ($6.node) {
- t = $6.node;
+ if ($4.loop) {
+ t = assembler->currentEdgeSource();
+ } else if ($4.cycle) {
+ t = assembler->currentPathSource();
+ if (!t) t = s;
} else {
- t = s;
+ t = $4.node;
}
- // if the source or the target of the edge doesn't exist, quietly ignore it.
- if (s != 0 && t != 0) {
- Edge *edge = new Edge(s, t);
- if ($2) {
- edge->setData($2);
- edge->setAttributesFromData();
- }
+ if (s != 0 && t != 0) { // if source or target don't exist, quietly ignore edge
+ Edge *e = new Edge(s, t);
+ assembler->setCurrentEdgeSource(t);
- if ($5)
- edge->setEdgeNode($5);
- if ($3.anchor) {
- edge->setSourceAnchor(QString($3.anchor));
- free($3.anchor);
+ if (!assembler->currentEdgeSourceAnchor().isEmpty()) {
+ e->setSourceAnchor(assembler->currentEdgeSourceAnchor());
}
- if ($6.node) {
- if ($6.anchor) {
- edge->setTargetAnchor(QString($6.anchor));
- free($6.anchor);
- }
+ if ($4.anchor) {
+ QString a($4.anchor);
+ free($4.anchor);
+ e->setTargetAnchor(a);
+ assembler->setCurrentEdgeSourceAnchor(a);
} else {
- edge->setTargetAnchor(edge->sourceAnchor());
+ assembler->setCurrentEdgeSourceAnchor(QString());
}
- assembler->graph()->addEdge(edge);
+ if ($3) e->setEdgeNode($3);
+
+ GraphElementData *cd = assembler->currentEdgeData();
+ if ($2) {
+ if (cd) $2->mergeData(cd);
+ e->setData($2);
+ } else {
+ if (cd) e->setData(cd->copy());
+ }
+ e->setAttributesFromData();
+ assembler->addEdge(e);
}
+ }
+
+
+edge: "\\draw" edgesource edgetarget optedgetargets ";"
+ {
+ assembler->finishCurrentPath();
};
ignoreprop: val | val "=" val;
diff --git a/src/data/tikzparserdefs.h b/src/data/tikzparserdefs.h
index 02743fe..da60bbf 100644
--- a/src/data/tikzparserdefs.h
+++ b/src/data/tikzparserdefs.h
@@ -33,6 +33,8 @@
struct noderef {
Node *node;
char *anchor;
+ bool cycle;
+ bool loop;
};
inline int isatty(int) { return 0; }