diff options
Diffstat (limited to 'src/data')
-rw-r--r-- | src/data/edge.cpp | 826 | ||||
-rw-r--r-- | src/data/edge.h | 260 | ||||
-rw-r--r-- | src/data/edgestyle.cpp | 262 | ||||
-rw-r--r-- | src/data/edgestyle.h | 112 | ||||
-rw-r--r-- | src/data/graph.cpp | 546 | ||||
-rw-r--r-- | src/data/graph.h | 218 | ||||
-rw-r--r-- | src/data/graphelementdata.cpp | 410 | ||||
-rw-r--r-- | src/data/graphelementdata.h | 178 | ||||
-rw-r--r-- | src/data/graphelementproperty.cpp | 154 | ||||
-rw-r--r-- | src/data/graphelementproperty.h | 116 | ||||
-rw-r--r-- | src/data/node.cpp | 236 | ||||
-rw-r--r-- | src/data/node.h | 144 | ||||
-rw-r--r-- | src/data/nodestyle.cpp | 214 | ||||
-rw-r--r-- | src/data/nodestyle.h | 102 | ||||
-rw-r--r-- | src/data/style.cpp | 156 | ||||
-rw-r--r-- | src/data/style.h | 108 | ||||
-rw-r--r-- | src/data/tikzassembler.cpp | 144 | ||||
-rw-r--r-- | src/data/tikzassembler.h | 120 | ||||
-rw-r--r-- | src/data/tikzdocument.cpp | 382 | ||||
-rw-r--r-- | src/data/tikzdocument.h | 138 | ||||
-rw-r--r-- | src/data/tikzlexer.l | 382 | ||||
-rw-r--r-- | src/data/tikzparser.y | 568 | ||||
-rw-r--r-- | src/data/tikzparserdefs.h | 80 | ||||
-rw-r--r-- | src/data/tikzstyles.cpp | 142 | ||||
-rw-r--r-- | src/data/tikzstyles.h | 102 |
25 files changed, 3050 insertions, 3050 deletions
diff --git a/src/data/edge.cpp b/src/data/edge.cpp index d741c56..8b2a851 100644 --- a/src/data/edge.cpp +++ b/src/data/edge.cpp @@ -1,413 +1,413 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#include "edge.h" -#include "tikzit.h" -#include "util.h" - -#include <QDebug> -#include <QPointF> - -Edge::Edge(Node *s, Node *t, QObject *parent) : - QObject(parent), _source(s), _target(t) -{ - _data = new GraphElementData(); - _edgeNode = 0; - _dirty = true; - _basicBendMode = true; - _bend = 0; - _inAngle = 0; - _outAngle = 0; - _weight = 0.4f; - _style = noneEdgeStyle; - updateControls(); -} - -Edge::~Edge() -{ - delete _data; - delete _edgeNode; -} - -/*! - * @brief Edge::copy makes a deep copy of an edge. - * @param nodeTable is an optional pointer to a table mapping the old source/target - * node pointers to their new, copied versions. This is used when making a copy of - * an entire (sub)graph. - * @return a copy of the edge - */ -Edge *Edge::copy(QMap<Node*,Node*> *nodeTable) -{ - Edge *e; - if (nodeTable == 0) e = new Edge(_source, _target); - else e = new Edge(nodeTable->value(_source), nodeTable->value(_target)); - e->setData(_data->copy()); - e->setBasicBendMode(_basicBendMode); - e->setBend(_bend); - e->setInAngle(_inAngle); - e->setOutAngle(_outAngle); - e->setWeight(_weight); - e->attachStyle(); - e->updateControls(); - return e; -} - -Node *Edge::source() const -{ - return _source; -} - -Node *Edge::target() const -{ - return _target; -} - -bool Edge::isSelfLoop() -{ - return (_source == _target); -} - -bool Edge::isStraight() -{ - return (_basicBendMode && _bend == 0); -} - -GraphElementData *Edge::data() const -{ - return _data; -} - -void Edge::setData(GraphElementData *data) -{ - delete _data; - _data = data; - setAttributesFromData(); -} - -QString Edge::styleName() const -{ - QString nm = _data->property("style"); - if (nm.isNull()) return "none"; - else return nm; -} - -void Edge::setStyleName(const QString &styleName) -{ - if (!styleName.isNull() && styleName != "none") _data->setProperty("style", styleName); - else _data->unsetProperty("style"); -} - -QString Edge::sourceAnchor() const -{ - return _sourceAnchor; -} - -void Edge::setSourceAnchor(const QString &sourceAnchor) -{ - _sourceAnchor = sourceAnchor; -} - -QString Edge::targetAnchor() const -{ - return _targetAnchor; -} - -void Edge::setTargetAnchor(const QString &targetAnchor) -{ - _targetAnchor = targetAnchor; -} - -Node *Edge::edgeNode() const -{ - return _edgeNode; -} - -void Edge::setEdgeNode(Node *edgeNode) -{ - if (_edgeNode != 0) delete _edgeNode; - _edgeNode = edgeNode; -} - -bool Edge::hasEdgeNode() -{ - return _edgeNode != 0; -} - -void Edge::updateControls() { - //if (_dirty) { - QPointF src = _source->point(); - QPointF targ = _target->point(); - - float dx = (targ.x() - src.x()); - float dy = (targ.y() - src.y()); - - float outAngleR = 0.0f; - float inAngleR = 0.0f; - - if (_basicBendMode) { - float angle = std::atan2(dy, dx); - float bnd = (float)_bend * (M_PI / 180.0f); - outAngleR = angle - bnd; - inAngleR = M_PI + angle + bnd; - _outAngle = outAngleR * (180.f / M_PI); - _inAngle = inAngleR * (180.f / M_PI); - } else { - outAngleR = (float)_outAngle * (M_PI / 180.0f); - inAngleR = (float)_inAngle * (M_PI / 180.0f); - } - - // TODO: calculate head and tail properly, not just for circles - if (_source->style()->isNone()) { - _tail = src; - } else { - _tail = QPointF(src.x() + std::cos(outAngleR) * 0.2, - src.y() + std::sin(outAngleR) * 0.2); - } - - if (_target->style()->isNone()) { - _head = targ; - } else { - _head = QPointF(targ.x() + std::cos(inAngleR) * 0.2, - targ.y() + std::sin(inAngleR) * 0.2); - } - - // give a default distance for self-loops - _cpDist = (dx==0.0f && dy==0.0f) ? _weight : std::sqrt(dx*dx + dy*dy) * _weight; - - _cp1 = QPointF(src.x() + (_cpDist * std::cos(outAngleR)), - src.y() + (_cpDist * std::sin(outAngleR))); - - _cp2 = QPointF(targ.x() + (_cpDist * std::cos(inAngleR)), - targ.y() + (_cpDist * std::sin(inAngleR))); - - _mid = bezierInterpolateFull (0.5f, _tail, _cp1, _cp2, _head); - _tailTangent = bezierTangent(0.0f, 0.1f); - _headTangent = bezierTangent(1.0f, 0.9f); -} - -void Edge::setAttributesFromData() -{ - _basicBendMode = true; - bool ok = true; - - if (_data->atom("bend left")) { - _bend = -30; - } else if (_data->atom("bend right")) { - _bend = 30; - } else if (_data->property("bend left") != 0) { - _bend = -_data->property("bend left").toInt(&ok); - if (!ok) _bend = -30; - } else if (_data->property("bend right") != 0) { - _bend = _data->property("bend right").toInt(&ok); - if (!ok) _bend = 30; - } else { - _bend = 0; - - if (_data->property("in") != 0 && _data->property("out") != 0) { - _basicBendMode = false; - _inAngle = _data->property("in").toInt(&ok); - if (!ok) _inAngle = 0; - _outAngle = _data->property("out").toInt(&ok); - if (!ok) _outAngle = 180; - } - } - - if (_data->property("looseness") != 0) { - _weight = _data->property("looseness").toFloat(&ok) / 2.5f; - if (!ok) _weight = 0.4f; - } else { - _weight = (isSelfLoop()) ? 1.0f : 0.4f; - } - - //qDebug() << "bend: " << _bend << " in: " << _inAngle << " out: " << _outAngle; - _dirty = true; -} - -void Edge::updateData() -{ - _data->unsetAtom("loop"); - _data->unsetProperty("in"); - _data->unsetProperty("out"); - _data->unsetAtom("bend left"); - _data->unsetAtom("bend right"); - _data->unsetProperty("bend left"); - _data->unsetProperty("bend right"); - _data->unsetProperty("looseness"); - - // TODO: style handling? - - if (_basicBendMode) { - if (_bend != 0) { - QString bendKey; - int b; - if (_bend < 0) { - bendKey = "bend left"; - b = -_bend; - } else { - bendKey = "bend right"; - b = _bend; - } - - if (b == 30) { - _data->setAtom(bendKey); - } else { - _data->setProperty(bendKey, QString::number(b)); - } - } - } else { - _data->setProperty("in", QString::number(_inAngle)); - _data->setProperty("out", QString::number(_outAngle)); - } - - if (_source == _target) _data->setAtom("loop"); - if (!isSelfLoop() && !isStraight() && _weight != 0.4f) - _data->setProperty("looseness", QString::number(_weight*2.5f, 'f', 2)); - if (_source->style()->isNone()) _sourceAnchor = "center"; - if (_target->style()->isNone()) _targetAnchor = "center"; - -} - - -QPointF Edge::head() const -{ - return _head; -} - -QPointF Edge::tail() const -{ - return _tail; -} - -QPointF Edge::cp1() const -{ - return _cp1; -} - -QPointF Edge::cp2() const -{ - return _cp2; -} - -int Edge::bend() const -{ - return _bend; -} - -int Edge::inAngle() const -{ - return _inAngle; -} - -int Edge::outAngle() const -{ - return _outAngle; -} - -float Edge::weight() const -{ - return _weight; -} - -bool Edge::basicBendMode() const -{ - return _basicBendMode; -} - -float Edge::cpDist() const -{ - return _cpDist; -} - -void Edge::setBasicBendMode(bool mode) -{ - _basicBendMode = mode; -} - -void Edge::setBend(int bend) -{ - _bend = bend; -} - -void Edge::setInAngle(int inAngle) -{ - _inAngle = inAngle; -} - -void Edge::setOutAngle(int outAngle) -{ - _outAngle = outAngle; -} - -void Edge::setWeight(float weight) -{ - _weight = weight; -} - -int Edge::tikzLine() const -{ - return _tikzLine; -} - -void Edge::setTikzLine(int tikzLine) -{ - _tikzLine = tikzLine; -} - -QPointF Edge::mid() const -{ - return _mid; -} - -QPointF Edge::headTangent() const -{ - return _headTangent; -} - -QPointF Edge::tailTangent() const -{ - return _tailTangent; -} - -void Edge::attachStyle() -{ - QString nm = styleName(); - if (nm.isNull()) _style = noneEdgeStyle; - else _style = tikzit->styles()->edgeStyle(nm); -} - -EdgeStyle * Edge::style() const -{ - return _style; -} - -QPointF Edge::bezierTangent(float start, float end) const -{ - float dx = bezierInterpolate(end, _tail.x(), _cp1.x(), _cp2.x(), _head.x()) - - bezierInterpolate(start, _tail.x(), _cp1.x(), _cp2.x(), _head.x()); - float dy = bezierInterpolate(end, _tail.y(), _cp1.y(), _cp2.y(), _head.y()) - - bezierInterpolate(start, _tail.y(), _cp1.y(), _cp2.y(), _head.y()); - - // normalise - float len = sqrt(dx*dx + dy * dy); - if (len != 0) { - dx = (dx / len) * 0.1f; - dy = (dy / len) * 0.1f; - } - - return QPointF(dx, dy); -} +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "edge.h"
+#include "tikzit.h"
+#include "util.h"
+
+#include <QDebug>
+#include <QPointF>
+
+Edge::Edge(Node *s, Node *t, QObject *parent) :
+ QObject(parent), _source(s), _target(t)
+{
+ _data = new GraphElementData();
+ _edgeNode = 0;
+ _dirty = true;
+ _basicBendMode = true;
+ _bend = 0;
+ _inAngle = 0;
+ _outAngle = 0;
+ _weight = 0.4f;
+ _style = noneEdgeStyle;
+ updateControls();
+}
+
+Edge::~Edge()
+{
+ delete _data;
+ delete _edgeNode;
+}
+
+/*!
+ * @brief Edge::copy makes a deep copy of an edge.
+ * @param nodeTable is an optional pointer to a table mapping the old source/target
+ * node pointers to their new, copied versions. This is used when making a copy of
+ * an entire (sub)graph.
+ * @return a copy of the edge
+ */
+Edge *Edge::copy(QMap<Node*,Node*> *nodeTable)
+{
+ Edge *e;
+ if (nodeTable == 0) e = new Edge(_source, _target);
+ else e = new Edge(nodeTable->value(_source), nodeTable->value(_target));
+ e->setData(_data->copy());
+ e->setBasicBendMode(_basicBendMode);
+ e->setBend(_bend);
+ e->setInAngle(_inAngle);
+ e->setOutAngle(_outAngle);
+ e->setWeight(_weight);
+ e->attachStyle();
+ e->updateControls();
+ return e;
+}
+
+Node *Edge::source() const
+{
+ return _source;
+}
+
+Node *Edge::target() const
+{
+ return _target;
+}
+
+bool Edge::isSelfLoop()
+{
+ return (_source == _target);
+}
+
+bool Edge::isStraight()
+{
+ return (_basicBendMode && _bend == 0);
+}
+
+GraphElementData *Edge::data() const
+{
+ return _data;
+}
+
+void Edge::setData(GraphElementData *data)
+{
+ delete _data;
+ _data = data;
+ setAttributesFromData();
+}
+
+QString Edge::styleName() const
+{
+ QString nm = _data->property("style");
+ if (nm.isNull()) return "none";
+ else return nm;
+}
+
+void Edge::setStyleName(const QString &styleName)
+{
+ if (!styleName.isNull() && styleName != "none") _data->setProperty("style", styleName);
+ else _data->unsetProperty("style");
+}
+
+QString Edge::sourceAnchor() const
+{
+ return _sourceAnchor;
+}
+
+void Edge::setSourceAnchor(const QString &sourceAnchor)
+{
+ _sourceAnchor = sourceAnchor;
+}
+
+QString Edge::targetAnchor() const
+{
+ return _targetAnchor;
+}
+
+void Edge::setTargetAnchor(const QString &targetAnchor)
+{
+ _targetAnchor = targetAnchor;
+}
+
+Node *Edge::edgeNode() const
+{
+ return _edgeNode;
+}
+
+void Edge::setEdgeNode(Node *edgeNode)
+{
+ if (_edgeNode != 0) delete _edgeNode;
+ _edgeNode = edgeNode;
+}
+
+bool Edge::hasEdgeNode()
+{
+ return _edgeNode != 0;
+}
+
+void Edge::updateControls() {
+ //if (_dirty) {
+ QPointF src = _source->point();
+ QPointF targ = _target->point();
+
+ float dx = (targ.x() - src.x());
+ float dy = (targ.y() - src.y());
+
+ float outAngleR = 0.0f;
+ float inAngleR = 0.0f;
+
+ if (_basicBendMode) {
+ float angle = std::atan2(dy, dx);
+ float bnd = (float)_bend * (M_PI / 180.0f);
+ outAngleR = angle - bnd;
+ inAngleR = M_PI + angle + bnd;
+ _outAngle = outAngleR * (180.f / M_PI);
+ _inAngle = inAngleR * (180.f / M_PI);
+ } else {
+ outAngleR = (float)_outAngle * (M_PI / 180.0f);
+ inAngleR = (float)_inAngle * (M_PI / 180.0f);
+ }
+
+ // TODO: calculate head and tail properly, not just for circles
+ if (_source->style()->isNone()) {
+ _tail = src;
+ } else {
+ _tail = QPointF(src.x() + std::cos(outAngleR) * 0.2,
+ src.y() + std::sin(outAngleR) * 0.2);
+ }
+
+ if (_target->style()->isNone()) {
+ _head = targ;
+ } else {
+ _head = QPointF(targ.x() + std::cos(inAngleR) * 0.2,
+ targ.y() + std::sin(inAngleR) * 0.2);
+ }
+
+ // give a default distance for self-loops
+ _cpDist = (dx==0.0f && dy==0.0f) ? _weight : std::sqrt(dx*dx + dy*dy) * _weight;
+
+ _cp1 = QPointF(src.x() + (_cpDist * std::cos(outAngleR)),
+ src.y() + (_cpDist * std::sin(outAngleR)));
+
+ _cp2 = QPointF(targ.x() + (_cpDist * std::cos(inAngleR)),
+ targ.y() + (_cpDist * std::sin(inAngleR)));
+
+ _mid = bezierInterpolateFull (0.5f, _tail, _cp1, _cp2, _head);
+ _tailTangent = bezierTangent(0.0f, 0.1f);
+ _headTangent = bezierTangent(1.0f, 0.9f);
+}
+
+void Edge::setAttributesFromData()
+{
+ _basicBendMode = true;
+ bool ok = true;
+
+ if (_data->atom("bend left")) {
+ _bend = -30;
+ } else if (_data->atom("bend right")) {
+ _bend = 30;
+ } else if (_data->property("bend left") != 0) {
+ _bend = -_data->property("bend left").toInt(&ok);
+ if (!ok) _bend = -30;
+ } else if (_data->property("bend right") != 0) {
+ _bend = _data->property("bend right").toInt(&ok);
+ if (!ok) _bend = 30;
+ } else {
+ _bend = 0;
+
+ if (_data->property("in") != 0 && _data->property("out") != 0) {
+ _basicBendMode = false;
+ _inAngle = _data->property("in").toInt(&ok);
+ if (!ok) _inAngle = 0;
+ _outAngle = _data->property("out").toInt(&ok);
+ if (!ok) _outAngle = 180;
+ }
+ }
+
+ if (_data->property("looseness") != 0) {
+ _weight = _data->property("looseness").toFloat(&ok) / 2.5f;
+ if (!ok) _weight = 0.4f;
+ } else {
+ _weight = (isSelfLoop()) ? 1.0f : 0.4f;
+ }
+
+ //qDebug() << "bend: " << _bend << " in: " << _inAngle << " out: " << _outAngle;
+ _dirty = true;
+}
+
+void Edge::updateData()
+{
+ _data->unsetAtom("loop");
+ _data->unsetProperty("in");
+ _data->unsetProperty("out");
+ _data->unsetAtom("bend left");
+ _data->unsetAtom("bend right");
+ _data->unsetProperty("bend left");
+ _data->unsetProperty("bend right");
+ _data->unsetProperty("looseness");
+
+ // TODO: style handling?
+
+ if (_basicBendMode) {
+ if (_bend != 0) {
+ QString bendKey;
+ int b;
+ if (_bend < 0) {
+ bendKey = "bend left";
+ b = -_bend;
+ } else {
+ bendKey = "bend right";
+ b = _bend;
+ }
+
+ if (b == 30) {
+ _data->setAtom(bendKey);
+ } else {
+ _data->setProperty(bendKey, QString::number(b));
+ }
+ }
+ } else {
+ _data->setProperty("in", QString::number(_inAngle));
+ _data->setProperty("out", QString::number(_outAngle));
+ }
+
+ if (_source == _target) _data->setAtom("loop");
+ if (!isSelfLoop() && !isStraight() && _weight != 0.4f)
+ _data->setProperty("looseness", QString::number(_weight*2.5f, 'f', 2));
+ if (_source->style()->isNone()) _sourceAnchor = "center";
+ if (_target->style()->isNone()) _targetAnchor = "center";
+
+}
+
+
+QPointF Edge::head() const
+{
+ return _head;
+}
+
+QPointF Edge::tail() const
+{
+ return _tail;
+}
+
+QPointF Edge::cp1() const
+{
+ return _cp1;
+}
+
+QPointF Edge::cp2() const
+{
+ return _cp2;
+}
+
+int Edge::bend() const
+{
+ return _bend;
+}
+
+int Edge::inAngle() const
+{
+ return _inAngle;
+}
+
+int Edge::outAngle() const
+{
+ return _outAngle;
+}
+
+float Edge::weight() const
+{
+ return _weight;
+}
+
+bool Edge::basicBendMode() const
+{
+ return _basicBendMode;
+}
+
+float Edge::cpDist() const
+{
+ return _cpDist;
+}
+
+void Edge::setBasicBendMode(bool mode)
+{
+ _basicBendMode = mode;
+}
+
+void Edge::setBend(int bend)
+{
+ _bend = bend;
+}
+
+void Edge::setInAngle(int inAngle)
+{
+ _inAngle = inAngle;
+}
+
+void Edge::setOutAngle(int outAngle)
+{
+ _outAngle = outAngle;
+}
+
+void Edge::setWeight(float weight)
+{
+ _weight = weight;
+}
+
+int Edge::tikzLine() const
+{
+ return _tikzLine;
+}
+
+void Edge::setTikzLine(int tikzLine)
+{
+ _tikzLine = tikzLine;
+}
+
+QPointF Edge::mid() const
+{
+ return _mid;
+}
+
+QPointF Edge::headTangent() const
+{
+ return _headTangent;
+}
+
+QPointF Edge::tailTangent() const
+{
+ return _tailTangent;
+}
+
+void Edge::attachStyle()
+{
+ QString nm = styleName();
+ if (nm.isNull()) _style = noneEdgeStyle;
+ else _style = tikzit->styles()->edgeStyle(nm);
+}
+
+EdgeStyle * Edge::style() const
+{
+ return _style;
+}
+
+QPointF Edge::bezierTangent(float start, float end) const
+{
+ float dx = bezierInterpolate(end, _tail.x(), _cp1.x(), _cp2.x(), _head.x()) -
+ bezierInterpolate(start, _tail.x(), _cp1.x(), _cp2.x(), _head.x());
+ float dy = bezierInterpolate(end, _tail.y(), _cp1.y(), _cp2.y(), _head.y()) -
+ bezierInterpolate(start, _tail.y(), _cp1.y(), _cp2.y(), _head.y());
+
+ // normalise
+ float len = sqrt(dx*dx + dy * dy);
+ if (len != 0) {
+ dx = (dx / len) * 0.1f;
+ dy = (dy / len) * 0.1f;
+ }
+
+ return QPointF(dx, dy);
+}
diff --git a/src/data/edge.h b/src/data/edge.h index dd09469..85959bb 100644 --- a/src/data/edge.h +++ b/src/data/edge.h @@ -1,130 +1,130 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#ifndef EDGE_H -#define EDGE_H - -#include "graphelementdata.h" -#include "node.h" -#include "edgestyle.h" - -#include <QObject> -#include <QPointF> - -class Edge : public QObject -{ - Q_OBJECT -public: - explicit Edge(Node *s, Node *t, QObject *parent = 0); - ~Edge(); - Edge *copy(QMap<Node *, Node *> *nodeTable = 0); - - Node *source() const; - Node *target() const; - - bool isSelfLoop(); - bool isStraight(); - - GraphElementData *data() const; - void setData(GraphElementData *data); - - QString sourceAnchor() const; - void setSourceAnchor(const QString &sourceAnchor); - - QString targetAnchor() const; - void setTargetAnchor(const QString &targetAnchor); - - Node *edgeNode() const; - void setEdgeNode(Node *edgeNode); - bool hasEdgeNode(); - - void updateControls(); - void setAttributesFromData(); - void updateData(); - - QPointF head() const; - QPointF tail() const; - QPointF cp1() const; - QPointF cp2() const; - QPointF mid() const; - QPointF headTangent() const; - QPointF tailTangent() const; - - int bend() const; - int inAngle() const; - int outAngle() const; - float weight() const; - bool basicBendMode() const; - float cpDist() const; - - void setBasicBendMode(bool mode); - void setBend(int bend); - void setInAngle(int inAngle); - void setOutAngle(int outAngle); - void setWeight(float weight); - - int tikzLine() const; - void setTikzLine(int tikzLine); - - - void attachStyle(); - QString styleName() const; - void setStyleName(const QString & styleName); - EdgeStyle *style() const; - -signals: - -public slots: - -private: - QPointF bezierTangent(float start, float end) const; - QString _sourceAnchor; - QString _targetAnchor; - - // owned - Node *_edgeNode; - GraphElementData *_data; - - // referenced - Node *_source; - Node *_target; - - - EdgeStyle *_style; - - bool _dirty; - bool _basicBendMode; - int _bend; - int _inAngle; - int _outAngle; - float _weight; - float _cpDist; - - QPointF _head; - QPointF _tail; - QPointF _cp1; - QPointF _cp2; - QPointF _mid; - - QPointF _headTangent; - QPointF _tailTangent; - - int _tikzLine; -}; - -#endif // EDGE_H +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef EDGE_H
+#define EDGE_H
+
+#include "graphelementdata.h"
+#include "node.h"
+#include "edgestyle.h"
+
+#include <QObject>
+#include <QPointF>
+
+class Edge : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Edge(Node *s, Node *t, QObject *parent = 0);
+ ~Edge();
+ Edge *copy(QMap<Node *, Node *> *nodeTable = 0);
+
+ Node *source() const;
+ Node *target() const;
+
+ bool isSelfLoop();
+ bool isStraight();
+
+ GraphElementData *data() const;
+ void setData(GraphElementData *data);
+
+ QString sourceAnchor() const;
+ void setSourceAnchor(const QString &sourceAnchor);
+
+ QString targetAnchor() const;
+ void setTargetAnchor(const QString &targetAnchor);
+
+ Node *edgeNode() const;
+ void setEdgeNode(Node *edgeNode);
+ bool hasEdgeNode();
+
+ void updateControls();
+ void setAttributesFromData();
+ void updateData();
+
+ QPointF head() const;
+ QPointF tail() const;
+ QPointF cp1() const;
+ QPointF cp2() const;
+ QPointF mid() const;
+ QPointF headTangent() const;
+ QPointF tailTangent() const;
+
+ int bend() const;
+ int inAngle() const;
+ int outAngle() const;
+ float weight() const;
+ bool basicBendMode() const;
+ float cpDist() const;
+
+ void setBasicBendMode(bool mode);
+ void setBend(int bend);
+ void setInAngle(int inAngle);
+ void setOutAngle(int outAngle);
+ void setWeight(float weight);
+
+ int tikzLine() const;
+ void setTikzLine(int tikzLine);
+
+
+ void attachStyle();
+ QString styleName() const;
+ void setStyleName(const QString & styleName);
+ EdgeStyle *style() const;
+
+signals:
+
+public slots:
+
+private:
+ QPointF bezierTangent(float start, float end) const;
+ QString _sourceAnchor;
+ QString _targetAnchor;
+
+ // owned
+ Node *_edgeNode;
+ GraphElementData *_data;
+
+ // referenced
+ Node *_source;
+ Node *_target;
+
+
+ EdgeStyle *_style;
+
+ bool _dirty;
+ bool _basicBendMode;
+ int _bend;
+ int _inAngle;
+ int _outAngle;
+ float _weight;
+ float _cpDist;
+
+ QPointF _head;
+ QPointF _tail;
+ QPointF _cp1;
+ QPointF _cp2;
+ QPointF _mid;
+
+ QPointF _headTangent;
+ QPointF _tailTangent;
+
+ int _tikzLine;
+};
+
+#endif // EDGE_H
diff --git a/src/data/edgestyle.cpp b/src/data/edgestyle.cpp index 079d4f5..275393e 100644 --- a/src/data/edgestyle.cpp +++ b/src/data/edgestyle.cpp @@ -1,131 +1,131 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#include "edgestyle.h" - -#include <QPainter> -#include <QPixmap> - -EdgeStyle *noneEdgeStyle = new EdgeStyle(); - -EdgeStyle::EdgeStyle() : Style() -{ -} - -EdgeStyle::EdgeStyle(QString name, GraphElementData *data) : Style(name, data) -{ -} - -EdgeStyle::ArrowTipStyle EdgeStyle::arrowHead() const -{ - if (_data == 0) return NoTip; - - if (_data->atom("->") || _data->atom("<->") || _data->atom("|->")) return Pointer; - if (_data->atom("-|") || _data->atom("<-|") || _data->atom("|-|")) return Flat; - return NoTip; -} - -EdgeStyle::ArrowTipStyle EdgeStyle::arrowTail() const -{ - if (_data == 0) return NoTip; - if (_data->atom("<-") || _data->atom("<->") || _data->atom("<-|")) return Pointer; - if (_data->atom("|-") || _data->atom("|->") || _data->atom("|-|")) return Flat; - return NoTip; -} - -EdgeStyle::DrawStyle EdgeStyle::drawStyle() const -{ - if (_data == 0) return Solid; - if (_data->atom("dashed")) return Dashed; - if (_data->atom("dotted")) return Dotted; - return Solid; -} - -QPen EdgeStyle::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; - } - - return p; -} - -QPainterPath EdgeStyle::path() const -{ - return QPainterPath(); -} - -QPainterPath EdgeStyle::palettePath() const -{ - return QPainterPath(); -} - -QIcon EdgeStyle::icon() const -{ - // draw an icon matching the style - QPixmap px(100,100); - px.fill(Qt::transparent); - QPainter painter(&px); - - if (_data == 0) { - QPen pen(Qt::black); - pen.setWidth(3); - } else { - painter.setPen(pen()); - } - - 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); - painter.drawLine(90,50,80,60); - break; - case Flat: - painter.drawLine(90,40,90,60); - break; - } - - switch (arrowTail()) { - case Pointer: - painter.drawLine(10,50,20,40); - painter.drawLine(10,50,20,60); - break; - case Flat: - painter.drawLine(10,40,10,60); - break; - } - - - return QIcon(px); -} +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "edgestyle.h"
+
+#include <QPainter>
+#include <QPixmap>
+
+EdgeStyle *noneEdgeStyle = new EdgeStyle();
+
+EdgeStyle::EdgeStyle() : Style()
+{
+}
+
+EdgeStyle::EdgeStyle(QString name, GraphElementData *data) : Style(name, data)
+{
+}
+
+EdgeStyle::ArrowTipStyle EdgeStyle::arrowHead() const
+{
+ if (_data == 0) return NoTip;
+
+ if (_data->atom("->") || _data->atom("<->") || _data->atom("|->")) return Pointer;
+ if (_data->atom("-|") || _data->atom("<-|") || _data->atom("|-|")) return Flat;
+ return NoTip;
+}
+
+EdgeStyle::ArrowTipStyle EdgeStyle::arrowTail() const
+{
+ if (_data == 0) return NoTip;
+ if (_data->atom("<-") || _data->atom("<->") || _data->atom("<-|")) return Pointer;
+ if (_data->atom("|-") || _data->atom("|->") || _data->atom("|-|")) return Flat;
+ return NoTip;
+}
+
+EdgeStyle::DrawStyle EdgeStyle::drawStyle() const
+{
+ if (_data == 0) return Solid;
+ if (_data->atom("dashed")) return Dashed;
+ if (_data->atom("dotted")) return Dotted;
+ return Solid;
+}
+
+QPen EdgeStyle::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;
+ }
+
+ return p;
+}
+
+QPainterPath EdgeStyle::path() const
+{
+ return QPainterPath();
+}
+
+QPainterPath EdgeStyle::palettePath() const
+{
+ return QPainterPath();
+}
+
+QIcon EdgeStyle::icon() const
+{
+ // draw an icon matching the style
+ QPixmap px(100,100);
+ px.fill(Qt::transparent);
+ QPainter painter(&px);
+
+ if (_data == 0) {
+ QPen pen(Qt::black);
+ pen.setWidth(3);
+ } else {
+ painter.setPen(pen());
+ }
+
+ 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);
+ painter.drawLine(90,50,80,60);
+ break;
+ case Flat:
+ painter.drawLine(90,40,90,60);
+ break;
+ }
+
+ switch (arrowTail()) {
+ case Pointer:
+ painter.drawLine(10,50,20,40);
+ painter.drawLine(10,50,20,60);
+ break;
+ case Flat:
+ painter.drawLine(10,40,10,60);
+ break;
+ }
+
+
+ return QIcon(px);
+}
diff --git a/src/data/edgestyle.h b/src/data/edgestyle.h index cf55d06..069545e 100644 --- a/src/data/edgestyle.h +++ b/src/data/edgestyle.h @@ -1,56 +1,56 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#ifndef EDGESTYLE_H -#define EDGESTYLE_H - -#include "style.h" - -#include <QColor> -#include <QPen> -#include <QBrush> -#include <QPainterPath> -#include <QIcon> - -class EdgeStyle : public Style -{ -public: - EdgeStyle(); - EdgeStyle(QString name, GraphElementData *data); - - enum ArrowTipStyle { - Flat, Pointer, NoTip - }; - - enum DrawStyle { - Solid, Dotted, Dashed - }; - - ArrowTipStyle arrowHead() const; - ArrowTipStyle arrowTail() const; - DrawStyle drawStyle() const; - - QPen pen() const; - QPainterPath path() const override; - QPainterPath palettePath() const override; - QIcon icon() const override; -}; - -extern EdgeStyle *noneEdgeStyle; - -#endif // EDGESTYLE_H +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef EDGESTYLE_H
+#define EDGESTYLE_H
+
+#include "style.h"
+
+#include <QColor>
+#include <QPen>
+#include <QBrush>
+#include <QPainterPath>
+#include <QIcon>
+
+class EdgeStyle : public Style
+{
+public:
+ EdgeStyle();
+ EdgeStyle(QString name, GraphElementData *data);
+
+ enum ArrowTipStyle {
+ Flat, Pointer, NoTip
+ };
+
+ enum DrawStyle {
+ Solid, Dotted, Dashed
+ };
+
+ ArrowTipStyle arrowHead() const;
+ ArrowTipStyle arrowTail() const;
+ DrawStyle drawStyle() const;
+
+ QPen pen() const;
+ QPainterPath path() const override;
+ QPainterPath palettePath() const override;
+ QIcon icon() const override;
+};
+
+extern EdgeStyle *noneEdgeStyle;
+
+#endif // EDGESTYLE_H
diff --git a/src/data/graph.cpp b/src/data/graph.cpp index 00b2dce..7ed3e91 100644 --- a/src/data/graph.cpp +++ b/src/data/graph.cpp @@ -1,273 +1,273 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#include "graph.h" -#include "util.h" - -#include <QTextStream> -#include <QSet> -#include <QtAlgorithms> -#include <QDebug> -#include <algorithm> - -Graph::Graph(QObject *parent) : QObject(parent) -{ - _data = new GraphElementData(this); - _bbox = QRectF(0,0,0,0); -} - -Graph::~Graph() -{ -} - -// add a node. The graph claims ownership. -void Graph::addNode(Node *n) { - n->setParent(this); - _nodes << n; -} - -void Graph::addNode(Node *n, int index) -{ - n->setParent(this); - _nodes.insert(index, n); -} - -void Graph::removeNode(Node *n) { - // the node itself is not deleted, as it may still be referenced in an undo command. It will - // be deleted when graph is, via QObject memory management. - _nodes.removeOne(n); -} - - -void Graph::addEdge(Edge *e) -{ - e->setParent(this); - _edges << e; -} - -void Graph::addEdge(Edge *e, int index) -{ - e->setParent(this); - _edges.insert(index, e); -} - -void Graph::removeEdge(Edge *e) -{ - // the edge itself is not deleted, as it may still be referenced in an undo command. It will - // be deleted when graph is, via QObject memory management. - _edges.removeOne(e); -} - -int Graph::maxIntName() -{ - int max = -1; - int i; - bool ok; - foreach (Node *n, _nodes) { - i = n->name().toInt(&ok); - if (ok && i > max) max = i; - } - return max; -} - -QRectF Graph::realBbox() -{ - //float maxX = 0.0f; - QRectF rect = bbox(); - foreach (Node *n, _nodes) { - rect = rect.united(QRectF(n->point().x()-0.5f, - n->point().y()-0.5f, - 1.0f, 1.0f)); - } - - return rect; -} - -QString Graph::freshNodeName() -{ - return QString::number(maxIntName() + 1); -} - -void Graph::renameApart(Graph *graph) -{ - int i = graph->maxIntName() + 1; - foreach (Node *n, _nodes) { - n->setName(QString::number(i)); - i++; - } -} - -GraphElementData *Graph::data() const -{ - return _data; -} - -void Graph::setData(GraphElementData *data) -{ - delete _data; - _data = data; -} - -const QVector<Node*> &Graph::nodes() -{ - return _nodes; -} - -const QVector<Edge*> &Graph::edges() -{ - return _edges; -} - -QRectF Graph::bbox() const -{ - return _bbox; -} - -bool Graph::hasBbox() { - return !(_bbox == QRectF(0,0,0,0)); -} - -void Graph::clearBbox() { - _bbox = QRectF(0,0,0,0); -} - -QString Graph::tikz() -{ - QString str; - QTextStream code(&str); - int line = 0; - - code << "\\begin{tikzpicture}" << _data->tikz() << "\n"; - line++; - if (hasBbox()) { - code << "\t\\path [use as bounding box] (" - << _bbox.topLeft().x() << "," << _bbox.topLeft().y() - << ") rectangle (" - << _bbox.bottomRight().x() << "," << _bbox.bottomRight().y() - << ");\n"; - line++; - } - - if (!_nodes.isEmpty()) { - code << "\t\\begin{pgfonlayer}{nodelayer}\n"; - line++; - } - - Node *n; - foreach (n, _nodes) { - n->setTikzLine(line); - code << "\t\t\\node "; - - if (!n->data()->isEmpty()) - code << n->data()->tikz() << " "; - - code << "(" << n->name() << ") at (" - << floatToString(n->point().x()) - << ", " - << floatToString(n->point().y()) - << ") {" << n->label() << "};\n"; - line++; - } - - if (!_nodes.isEmpty()) { - code << "\t\\end{pgfonlayer}\n"; - line++; - } - - if (!_edges.isEmpty()) { - code << "\t\\begin{pgfonlayer}{edgelayer}\n"; - line++; - } - - - Edge *e; - 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() << "} "; - } - - if (e->source() == e->target()) { - code << "()"; - } else { - code << "(" << e->target()->name(); - if (e->targetAnchor() != "") - code << "." << e->targetAnchor(); - code << ")"; - } - - code << ";\n"; - line++; - } - - if (!_edges.isEmpty()) { - code << "\t\\end{pgfonlayer}\n"; - line++; - } - - code << "\\end{tikzpicture}\n"; - line++; - - code.flush(); - return str; -} - -Graph *Graph::copyOfSubgraphWithNodes(QSet<Node *> nds) -{ - Graph *g = new Graph(); - g->setData(_data->copy()); - QMap<Node*,Node*> nodeTable; - foreach (Node *n, nds) { - Node *n1 = n->copy(); - nodeTable.insert(n, n1); - g->addNode(n1); - } - foreach (Edge *e, edges()) { - if (nds.contains(e->source()) && nds.contains(e->target())) { - g->addEdge(e->copy(&nodeTable)); - } - } - - return g; -} - -void Graph::insertGraph(Graph *graph) -{ - QMap<Node*,Node*> nodeTable; - foreach (Node *n, graph->nodes()) addNode(n); - foreach (Edge *e, graph->edges()) addEdge(e); -} - -void Graph::setBbox(const QRectF &bbox) -{ - _bbox = bbox; -} +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "graph.h"
+#include "util.h"
+
+#include <QTextStream>
+#include <QSet>
+#include <QtAlgorithms>
+#include <QDebug>
+#include <algorithm>
+
+Graph::Graph(QObject *parent) : QObject(parent)
+{
+ _data = new GraphElementData(this);
+ _bbox = QRectF(0,0,0,0);
+}
+
+Graph::~Graph()
+{
+}
+
+// add a node. The graph claims ownership.
+void Graph::addNode(Node *n) {
+ n->setParent(this);
+ _nodes << n;
+}
+
+void Graph::addNode(Node *n, int index)
+{
+ n->setParent(this);
+ _nodes.insert(index, n);
+}
+
+void Graph::removeNode(Node *n) {
+ // the node itself is not deleted, as it may still be referenced in an undo command. It will
+ // be deleted when graph is, via QObject memory management.
+ _nodes.removeOne(n);
+}
+
+
+void Graph::addEdge(Edge *e)
+{
+ e->setParent(this);
+ _edges << e;
+}
+
+void Graph::addEdge(Edge *e, int index)
+{
+ e->setParent(this);
+ _edges.insert(index, e);
+}
+
+void Graph::removeEdge(Edge *e)
+{
+ // the edge itself is not deleted, as it may still be referenced in an undo command. It will
+ // be deleted when graph is, via QObject memory management.
+ _edges.removeOne(e);
+}
+
+int Graph::maxIntName()
+{
+ int max = -1;
+ int i;
+ bool ok;
+ foreach (Node *n, _nodes) {
+ i = n->name().toInt(&ok);
+ if (ok && i > max) max = i;
+ }
+ return max;
+}
+
+QRectF Graph::realBbox()
+{
+ //float maxX = 0.0f;
+ QRectF rect = bbox();
+ foreach (Node *n, _nodes) {
+ rect = rect.united(QRectF(n->point().x()-0.5f,
+ n->point().y()-0.5f,
+ 1.0f, 1.0f));
+ }
+
+ return rect;
+}
+
+QString Graph::freshNodeName()
+{
+ return QString::number(maxIntName() + 1);
+}
+
+void Graph::renameApart(Graph *graph)
+{
+ int i = graph->maxIntName() + 1;
+ foreach (Node *n, _nodes) {
+ n->setName(QString::number(i));
+ i++;
+ }
+}
+
+GraphElementData *Graph::data() const
+{
+ return _data;
+}
+
+void Graph::setData(GraphElementData *data)
+{
+ delete _data;
+ _data = data;
+}
+
+const QVector<Node*> &Graph::nodes()
+{
+ return _nodes;
+}
+
+const QVector<Edge*> &Graph::edges()
+{
+ return _edges;
+}
+
+QRectF Graph::bbox() const
+{
+ return _bbox;
+}
+
+bool Graph::hasBbox() {
+ return !(_bbox == QRectF(0,0,0,0));
+}
+
+void Graph::clearBbox() {
+ _bbox = QRectF(0,0,0,0);
+}
+
+QString Graph::tikz()
+{
+ QString str;
+ QTextStream code(&str);
+ int line = 0;
+
+ code << "\\begin{tikzpicture}" << _data->tikz() << "\n";
+ line++;
+ if (hasBbox()) {
+ code << "\t\\path [use as bounding box] ("
+ << _bbox.topLeft().x() << "," << _bbox.topLeft().y()
+ << ") rectangle ("
+ << _bbox.bottomRight().x() << "," << _bbox.bottomRight().y()
+ << ");\n";
+ line++;
+ }
+
+ if (!_nodes.isEmpty()) {
+ code << "\t\\begin{pgfonlayer}{nodelayer}\n";
+ line++;
+ }
+
+ Node *n;
+ foreach (n, _nodes) {
+ n->setTikzLine(line);
+ code << "\t\t\\node ";
+
+ if (!n->data()->isEmpty())
+ code << n->data()->tikz() << " ";
+
+ code << "(" << n->name() << ") at ("
+ << floatToString(n->point().x())
+ << ", "
+ << floatToString(n->point().y())
+ << ") {" << n->label() << "};\n";
+ line++;
+ }
+
+ if (!_nodes.isEmpty()) {
+ code << "\t\\end{pgfonlayer}\n";
+ line++;
+ }
+
+ if (!_edges.isEmpty()) {
+ code << "\t\\begin{pgfonlayer}{edgelayer}\n";
+ line++;
+ }
+
+
+ Edge *e;
+ 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() << "} ";
+ }
+
+ if (e->source() == e->target()) {
+ code << "()";
+ } else {
+ code << "(" << e->target()->name();
+ if (e->targetAnchor() != "")
+ code << "." << e->targetAnchor();
+ code << ")";
+ }
+
+ code << ";\n";
+ line++;
+ }
+
+ if (!_edges.isEmpty()) {
+ code << "\t\\end{pgfonlayer}\n";
+ line++;
+ }
+
+ code << "\\end{tikzpicture}\n";
+ line++;
+
+ code.flush();
+ return str;
+}
+
+Graph *Graph::copyOfSubgraphWithNodes(QSet<Node *> nds)
+{
+ Graph *g = new Graph();
+ g->setData(_data->copy());
+ QMap<Node*,Node*> nodeTable;
+ foreach (Node *n, nds) {
+ Node *n1 = n->copy();
+ nodeTable.insert(n, n1);
+ g->addNode(n1);
+ }
+ foreach (Edge *e, edges()) {
+ if (nds.contains(e->source()) && nds.contains(e->target())) {
+ g->addEdge(e->copy(&nodeTable));
+ }
+ }
+
+ return g;
+}
+
+void Graph::insertGraph(Graph *graph)
+{
+ QMap<Node*,Node*> nodeTable;
+ foreach (Node *n, graph->nodes()) addNode(n);
+ foreach (Edge *e, graph->edges()) addEdge(e);
+}
+
+void Graph::setBbox(const QRectF &bbox)
+{
+ _bbox = bbox;
+}
diff --git a/src/data/graph.h b/src/data/graph.h index 77af253..82e1f95 100644 --- a/src/data/graph.h +++ b/src/data/graph.h @@ -1,109 +1,109 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -/*! - * A graph defined by tikz code. - */ - -#ifndef GRAPH_H -#define GRAPH_H - -#include "node.h" -#include "edge.h" -#include "graphelementdata.h" - -#include <QObject> -#include <QVector> -#include <QMultiHash> -#include <QRectF> -#include <QString> - -class Graph : public QObject -{ - Q_OBJECT -public: - explicit Graph(QObject *parent = 0); - ~Graph(); - void addNode(Node *n); - void addNode(Node *n, int index); - void removeNode(Node *n); - void addEdge(Edge *e); - void addEdge(Edge *e, int index); - void removeEdge(Edge *e); - int maxIntName(); - QString freshNodeName(); - - /*! - * \brief renameApart assigns fresh names to all of the nodes in "this", - * with respect to the given graph - * \param graph - */ - void renameApart(Graph *graph); - - GraphElementData *data() const; - void setData(GraphElementData *data); - - const QVector<Node *> &nodes(); - const QVector<Edge*> &edges(); - - QRectF bbox() const; - void setBbox(const QRectF &bbox); - bool hasBbox(); - void clearBbox(); - - /*! - * \brief realBbox computes the union of the user-defined - * bounding box, and the bounding boxes of the graph's - * contents. - * - * \return - */ - QRectF realBbox(); - - QString tikz(); - - /*! - * \brief copyOfSubgraphWithNodes produces a copy of the full subgraph - * with the given nodes. Used for cutting and copying to clipboard. - * \param nds - * \return - */ - Graph *copyOfSubgraphWithNodes(QSet<Node*> nds); - - /*! - * \brief insertGraph inserts the given graph into "this". Prior to calling this - * method, the node names in the given graph should be made fresh via - * "renameApart". Note that the parameter "graph" relinquishes ownership of its - * nodes and edges, so it should be not be allowed to exist longer than "this". - * \param graph - */ - void insertGraph(Graph *graph); -signals: - -public slots: - -private: - QVector<Node*> _nodes; - QVector<Edge*> _edges; - //QMultiHash<Node*,Edge*> inEdges; - //QMultiHash<Node*,Edge*> outEdges; - GraphElementData *_data; - QRectF _bbox; -}; - -#endif // GRAPH_H +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+/*!
+ * A graph defined by tikz code.
+ */
+
+#ifndef GRAPH_H
+#define GRAPH_H
+
+#include "node.h"
+#include "edge.h"
+#include "graphelementdata.h"
+
+#include <QObject>
+#include <QVector>
+#include <QMultiHash>
+#include <QRectF>
+#include <QString>
+
+class Graph : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Graph(QObject *parent = 0);
+ ~Graph();
+ void addNode(Node *n);
+ void addNode(Node *n, int index);
+ void removeNode(Node *n);
+ void addEdge(Edge *e);
+ void addEdge(Edge *e, int index);
+ void removeEdge(Edge *e);
+ int maxIntName();
+ QString freshNodeName();
+
+ /*!
+ * \brief renameApart assigns fresh names to all of the nodes in "this",
+ * with respect to the given graph
+ * \param graph
+ */
+ void renameApart(Graph *graph);
+
+ GraphElementData *data() const;
+ void setData(GraphElementData *data);
+
+ const QVector<Node *> &nodes();
+ const QVector<Edge*> &edges();
+
+ QRectF bbox() const;
+ void setBbox(const QRectF &bbox);
+ bool hasBbox();
+ void clearBbox();
+
+ /*!
+ * \brief realBbox computes the union of the user-defined
+ * bounding box, and the bounding boxes of the graph's
+ * contents.
+ *
+ * \return
+ */
+ QRectF realBbox();
+
+ QString tikz();
+
+ /*!
+ * \brief copyOfSubgraphWithNodes produces a copy of the full subgraph
+ * with the given nodes. Used for cutting and copying to clipboard.
+ * \param nds
+ * \return
+ */
+ Graph *copyOfSubgraphWithNodes(QSet<Node*> nds);
+
+ /*!
+ * \brief insertGraph inserts the given graph into "this". Prior to calling this
+ * method, the node names in the given graph should be made fresh via
+ * "renameApart". Note that the parameter "graph" relinquishes ownership of its
+ * nodes and edges, so it should be not be allowed to exist longer than "this".
+ * \param graph
+ */
+ void insertGraph(Graph *graph);
+signals:
+
+public slots:
+
+private:
+ QVector<Node*> _nodes;
+ QVector<Edge*> _edges;
+ //QMultiHash<Node*,Edge*> inEdges;
+ //QMultiHash<Node*,Edge*> outEdges;
+ GraphElementData *_data;
+ QRectF _bbox;
+};
+
+#endif // GRAPH_H
diff --git a/src/data/graphelementdata.cpp b/src/data/graphelementdata.cpp index 5b35f63..fcd90ea 100644 --- a/src/data/graphelementdata.cpp +++ b/src/data/graphelementdata.cpp @@ -1,205 +1,205 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#include "graphelementdata.h" - -#include <QDebug> -#include <QTextStream> - -GraphElementData::GraphElementData(QVector<GraphElementProperty> init, QObject *parent) : QAbstractItemModel(parent) -{ - root = new GraphElementProperty(); - _properties = init; -} - -GraphElementData::GraphElementData(QObject *parent) : QAbstractItemModel(parent) { - root = new GraphElementProperty(); -} - -GraphElementData::~GraphElementData() -{ - delete root; -} - -GraphElementData *GraphElementData::copy() -{ - return new GraphElementData(_properties); -} - -void GraphElementData::setProperty(QString key, QString value) -{ - GraphElementProperty m(key, true); - int i = _properties.indexOf(m); - if (i != -1) { - _properties[i].setValue(value); - } else { - GraphElementProperty p(key, value); - _properties << p; - } -} - -void GraphElementData::unsetProperty(QString key) -{ - GraphElementProperty m(key, true); - int i = _properties.indexOf(m); - if (i != -1) - _properties.remove(i); -} - -void GraphElementData::add(GraphElementProperty p) -{ - _properties << p; -} - -void GraphElementData::operator <<(GraphElementProperty p) -{ - add(p); -} - -void GraphElementData::setAtom(QString atom) -{ - GraphElementProperty a(atom); - int i = _properties.indexOf(a); - if (i == -1) - _properties << a; -} - -void GraphElementData::unsetAtom(QString atom) -{ - GraphElementProperty a(atom); - int i = _properties.indexOf(a); - if (i != -1) - _properties.remove(i); -} - -QString GraphElementData::property(QString key) -{ - GraphElementProperty m(key, true); - int i = _properties.indexOf(m); - if (i != -1) { - return _properties[i].value(); - } else { - return QString(); // null QString - } -} - -bool GraphElementData::atom(QString atom) -{ - GraphElementProperty a(atom); - return (_properties.indexOf(a) != -1); -} - -QVariant GraphElementData::data(const QModelIndex &index, int role) const -{ - if (role != Qt::DisplayRole) - return QVariant(); - - if (index.row() >= 0 && index.row() < _properties.length()) { - const GraphElementProperty &p = _properties[index.row()]; - QString s = (index.column() == 0) ? p.key() : p.value(); - return QVariant(s); - } - - return QVariant(); -} - -QVariant GraphElementData::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { - if (section == 0) return QVariant("Key/Atom"); - else return QVariant("Value"); - } - - return QVariant(); -} - -QModelIndex GraphElementData::index(int row, int column, const QModelIndex &parent) const -{ - return createIndex(row, column, (void*)0); -} - -QModelIndex GraphElementData::parent(const QModelIndex &index) const -{ - GraphElementProperty *p = static_cast<GraphElementProperty*>(index.internalPointer()); - if (p == root) return QModelIndex(); - else return createIndex(0,0,static_cast<void*>(root)); -} - -int GraphElementData::rowCount(const QModelIndex &parent) const -{ - if (parent.isValid()) { - return 0; - } else { - return _properties.size(); - } -} - -int GraphElementData::columnCount(const QModelIndex &) const -{ - return 2; -} - -Qt::ItemFlags GraphElementData::flags(const QModelIndex &index) const -{ - return QAbstractItemModel::flags(index); -} - -//bool GraphElementData::setData(const QModelIndex &index, const QVariant &value, int role) -//{ - -//} - -//bool GraphElementData::insertRows(int position, int rows, const QModelIndex &parent) -//{ - -//} - -//bool GraphElementData::removeRows(int position, int rows, const QModelIndex &parent) -//{ - -//} - -QString GraphElementData::tikz() { - if (_properties.length() == 0) return ""; - QString str; - QTextStream code(&str); - code << "["; - - GraphElementProperty p; - bool first = true; - foreach(p, _properties) { - if (!first) code << ", "; - code << p.tikz(); - first = false; - } - - code << "]"; - - code.flush(); - return str; -} - -bool GraphElementData::isEmpty() -{ - return _properties.isEmpty(); -} - -QVector<GraphElementProperty> GraphElementData::properties() const -{ - return _properties; -} +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "graphelementdata.h"
+
+#include <QDebug>
+#include <QTextStream>
+
+GraphElementData::GraphElementData(QVector<GraphElementProperty> init, QObject *parent) : QAbstractItemModel(parent)
+{
+ root = new GraphElementProperty();
+ _properties = init;
+}
+
+GraphElementData::GraphElementData(QObject *parent) : QAbstractItemModel(parent) {
+ root = new GraphElementProperty();
+}
+
+GraphElementData::~GraphElementData()
+{
+ delete root;
+}
+
+GraphElementData *GraphElementData::copy()
+{
+ return new GraphElementData(_properties);
+}
+
+void GraphElementData::setProperty(QString key, QString value)
+{
+ GraphElementProperty m(key, true);
+ int i = _properties.indexOf(m);
+ if (i != -1) {
+ _properties[i].setValue(value);
+ } else {
+ GraphElementProperty p(key, value);
+ _properties << p;
+ }
+}
+
+void GraphElementData::unsetProperty(QString key)
+{
+ GraphElementProperty m(key, true);
+ int i = _properties.indexOf(m);
+ if (i != -1)
+ _properties.remove(i);
+}
+
+void GraphElementData::add(GraphElementProperty p)
+{
+ _properties << p;
+}
+
+void GraphElementData::operator <<(GraphElementProperty p)
+{
+ add(p);
+}
+
+void GraphElementData::setAtom(QString atom)
+{
+ GraphElementProperty a(atom);
+ int i = _properties.indexOf(a);
+ if (i == -1)
+ _properties << a;
+}
+
+void GraphElementData::unsetAtom(QString atom)
+{
+ GraphElementProperty a(atom);
+ int i = _properties.indexOf(a);
+ if (i != -1)
+ _properties.remove(i);
+}
+
+QString GraphElementData::property(QString key)
+{
+ GraphElementProperty m(key, true);
+ int i = _properties.indexOf(m);
+ if (i != -1) {
+ return _properties[i].value();
+ } else {
+ return QString(); // null QString
+ }
+}
+
+bool GraphElementData::atom(QString atom)
+{
+ GraphElementProperty a(atom);
+ return (_properties.indexOf(a) != -1);
+}
+
+QVariant GraphElementData::data(const QModelIndex &index, int role) const
+{
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ if (index.row() >= 0 && index.row() < _properties.length()) {
+ const GraphElementProperty &p = _properties[index.row()];
+ QString s = (index.column() == 0) ? p.key() : p.value();
+ return QVariant(s);
+ }
+
+ return QVariant();
+}
+
+QVariant GraphElementData::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+ if (section == 0) return QVariant("Key/Atom");
+ else return QVariant("Value");
+ }
+
+ return QVariant();
+}
+
+QModelIndex GraphElementData::index(int row, int column, const QModelIndex &parent) const
+{
+ return createIndex(row, column, (void*)0);
+}
+
+QModelIndex GraphElementData::parent(const QModelIndex &index) const
+{
+ GraphElementProperty *p = static_cast<GraphElementProperty*>(index.internalPointer());
+ if (p == root) return QModelIndex();
+ else return createIndex(0,0,static_cast<void*>(root));
+}
+
+int GraphElementData::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid()) {
+ return 0;
+ } else {
+ return _properties.size();
+ }
+}
+
+int GraphElementData::columnCount(const QModelIndex &) const
+{
+ return 2;
+}
+
+Qt::ItemFlags GraphElementData::flags(const QModelIndex &index) const
+{
+ return QAbstractItemModel::flags(index);
+}
+
+//bool GraphElementData::setData(const QModelIndex &index, const QVariant &value, int role)
+//{
+
+//}
+
+//bool GraphElementData::insertRows(int position, int rows, const QModelIndex &parent)
+//{
+
+//}
+
+//bool GraphElementData::removeRows(int position, int rows, const QModelIndex &parent)
+//{
+
+//}
+
+QString GraphElementData::tikz() {
+ if (_properties.length() == 0) return "";
+ QString str;
+ QTextStream code(&str);
+ code << "[";
+
+ GraphElementProperty p;
+ bool first = true;
+ foreach(p, _properties) {
+ if (!first) code << ", ";
+ code << p.tikz();
+ first = false;
+ }
+
+ code << "]";
+
+ code.flush();
+ return str;
+}
+
+bool GraphElementData::isEmpty()
+{
+ return _properties.isEmpty();
+}
+
+QVector<GraphElementProperty> GraphElementData::properties() const
+{
+ return _properties;
+}
diff --git a/src/data/graphelementdata.h b/src/data/graphelementdata.h index 58e57a0..2b27384 100644 --- a/src/data/graphelementdata.h +++ b/src/data/graphelementdata.h @@ -1,89 +1,89 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#ifndef GRAPHELEMENTDATA_H -#define GRAPHELEMENTDATA_H - -#include "graphelementproperty.h" - -#include <QAbstractItemModel> -#include <QString> -#include <QVariant> -#include <QModelIndex> -#include <QVector> - -class GraphElementData : public QAbstractItemModel -{ - Q_OBJECT -public: - explicit GraphElementData(QVector<GraphElementProperty> init, - QObject *parent = 0); - explicit GraphElementData(QObject *parent = 0); - ~GraphElementData(); - GraphElementData *copy(); - void setProperty(QString key, QString value); - void unsetProperty(QString key); - void setAtom(QString atom); - void unsetAtom(QString atom); - QString property(QString key); - bool atom(QString atom); - - QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; - - QModelIndex index(int row, int column, - const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; - - int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; - int columnCount(const QModelIndex &) const Q_DECL_OVERRIDE; - - Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE; - -// bool setData(const QModelIndex &index, const QVariant &value, -// int role = Qt::EditRole) Q_DECL_OVERRIDE; -// bool setHeaderData(int section, Qt::Orientation orientation, -// const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE; - -// bool insertColumns(int position, int columns, -// const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE; -// bool removeColumns(int position, int columns, -// const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE; -// bool insertRows(int position, int rows, -// const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE; -// bool removeRows(int position, int rows, -// const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE; - - void operator <<(GraphElementProperty p); - void add(GraphElementProperty p); - - QString tikz(); - bool isEmpty(); - QVector<GraphElementProperty> properties() const; - -signals: - -public slots: - -private: - QVector<GraphElementProperty> _properties; - GraphElementProperty *root; -}; - -#endif // GRAPHELEMENTDATA_H +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef GRAPHELEMENTDATA_H
+#define GRAPHELEMENTDATA_H
+
+#include "graphelementproperty.h"
+
+#include <QAbstractItemModel>
+#include <QString>
+#include <QVariant>
+#include <QModelIndex>
+#include <QVector>
+
+class GraphElementData : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ explicit GraphElementData(QVector<GraphElementProperty> init,
+ QObject *parent = 0);
+ explicit GraphElementData(QObject *parent = 0);
+ ~GraphElementData();
+ GraphElementData *copy();
+ void setProperty(QString key, QString value);
+ void unsetProperty(QString key);
+ void setAtom(QString atom);
+ void unsetAtom(QString atom);
+ QString property(QString key);
+ bool atom(QString atom);
+
+ QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
+ QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+
+ QModelIndex index(int row, int column,
+ const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
+ QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE;
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
+ int columnCount(const QModelIndex &) const Q_DECL_OVERRIDE;
+
+ Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
+
+// bool setData(const QModelIndex &index, const QVariant &value,
+// int role = Qt::EditRole) Q_DECL_OVERRIDE;
+// bool setHeaderData(int section, Qt::Orientation orientation,
+// const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE;
+
+// bool insertColumns(int position, int columns,
+// const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
+// bool removeColumns(int position, int columns,
+// const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
+// bool insertRows(int position, int rows,
+// const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
+// bool removeRows(int position, int rows,
+// const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
+
+ void operator <<(GraphElementProperty p);
+ void add(GraphElementProperty p);
+
+ QString tikz();
+ bool isEmpty();
+ QVector<GraphElementProperty> properties() const;
+
+signals:
+
+public slots:
+
+private:
+ QVector<GraphElementProperty> _properties;
+ GraphElementProperty *root;
+};
+
+#endif // GRAPHELEMENTDATA_H
diff --git a/src/data/graphelementproperty.cpp b/src/data/graphelementproperty.cpp index 0717952..79a8280 100644 --- a/src/data/graphelementproperty.cpp +++ b/src/data/graphelementproperty.cpp @@ -1,77 +1,77 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#include "graphelementproperty.h" - -#include <QRegExp> - -GraphElementProperty::GraphElementProperty (): - _key(""), _value(""), _atom(false), _keyMatch(false) -{} - -GraphElementProperty::GraphElementProperty(QString key, QString value, bool atom, bool keyMatch) : - _key(key), _value(value), _atom(atom), _keyMatch(keyMatch) -{} - -GraphElementProperty::GraphElementProperty(QString key, QString value) : - _key(key), _value(value), _atom(false), _keyMatch(false) -{} - -GraphElementProperty::GraphElementProperty(QString key, bool keyMatch) : - _key(key), _value(""), _atom(!keyMatch), _keyMatch(keyMatch) -{} - -QString GraphElementProperty::key() const -{ return _key; } - -QString GraphElementProperty::value() const -{ return _value; } - -void GraphElementProperty::setValue(const QString &value) -{ _value = value; } - -bool GraphElementProperty::atom() const -{ return _atom; } - -bool GraphElementProperty::keyMatch() const -{ return _keyMatch; } - -bool GraphElementProperty::matches(const GraphElementProperty &p) -{ - if (p.atom()) return _atom && _key == p.key(); - if (p.keyMatch()) return !_atom && _key == p.key(); - if (_keyMatch) return !p.atom() && _key == p.key(); - return !_atom && _key == p.key() && _value == p.value(); -} - -bool GraphElementProperty::operator==(const GraphElementProperty &p) -{ - return matches(p); -} - -QString GraphElementProperty::tikzEscape(QString str) -{ - QRegExp re("[0-9a-zA-Z<> \\-'.]*"); - if (re.exactMatch(str)) return str; - else return "{" + str + "}"; -} - -QString GraphElementProperty::tikz() { - if (_atom) return tikzEscape(_key); - return tikzEscape(_key) + "=" + tikzEscape(_value); -} +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "graphelementproperty.h"
+
+#include <QRegExp>
+
+GraphElementProperty::GraphElementProperty ():
+ _key(""), _value(""), _atom(false), _keyMatch(false)
+{}
+
+GraphElementProperty::GraphElementProperty(QString key, QString value, bool atom, bool keyMatch) :
+ _key(key), _value(value), _atom(atom), _keyMatch(keyMatch)
+{}
+
+GraphElementProperty::GraphElementProperty(QString key, QString value) :
+ _key(key), _value(value), _atom(false), _keyMatch(false)
+{}
+
+GraphElementProperty::GraphElementProperty(QString key, bool keyMatch) :
+ _key(key), _value(""), _atom(!keyMatch), _keyMatch(keyMatch)
+{}
+
+QString GraphElementProperty::key() const
+{ return _key; }
+
+QString GraphElementProperty::value() const
+{ return _value; }
+
+void GraphElementProperty::setValue(const QString &value)
+{ _value = value; }
+
+bool GraphElementProperty::atom() const
+{ return _atom; }
+
+bool GraphElementProperty::keyMatch() const
+{ return _keyMatch; }
+
+bool GraphElementProperty::matches(const GraphElementProperty &p)
+{
+ if (p.atom()) return _atom && _key == p.key();
+ if (p.keyMatch()) return !_atom && _key == p.key();
+ if (_keyMatch) return !p.atom() && _key == p.key();
+ return !_atom && _key == p.key() && _value == p.value();
+}
+
+bool GraphElementProperty::operator==(const GraphElementProperty &p)
+{
+ return matches(p);
+}
+
+QString GraphElementProperty::tikzEscape(QString str)
+{
+ QRegExp re("[0-9a-zA-Z<> \\-'.]*");
+ if (re.exactMatch(str)) return str;
+ else return "{" + str + "}";
+}
+
+QString GraphElementProperty::tikz() {
+ if (_atom) return tikzEscape(_key);
+ return tikzEscape(_key) + "=" + tikzEscape(_value);
+}
diff --git a/src/data/graphelementproperty.h b/src/data/graphelementproperty.h index d37f69e..af4ae91 100644 --- a/src/data/graphelementproperty.h +++ b/src/data/graphelementproperty.h @@ -1,58 +1,58 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#ifndef GRAPHELEMENTPROPERTY_H -#define GRAPHELEMENTPROPERTY_H - -#include <QObject> - -class GraphElementProperty -{ -public: - GraphElementProperty(); - GraphElementProperty(QString key, QString value, bool atom, bool keyMatch); - - // construct a property - GraphElementProperty(QString key, QString value); - - // construct an atom or keymatch - GraphElementProperty(QString key, bool keyMatch = false); - - QString key() const; - QString value() const; - void setValue(const QString &value); - bool atom() const; - bool keyMatch() const; - - bool matches(const GraphElementProperty &p); - bool operator==(const GraphElementProperty &p); - - static QString tikzEscape(QString str); - QString tikz(); -signals: - -public slots: - -private: - QString _key; - QString _value; - bool _atom; - bool _keyMatch; -}; - -#endif // GRAPHELEMENTPROPERTY_H +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef GRAPHELEMENTPROPERTY_H
+#define GRAPHELEMENTPROPERTY_H
+
+#include <QObject>
+
+class GraphElementProperty
+{
+public:
+ GraphElementProperty();
+ GraphElementProperty(QString key, QString value, bool atom, bool keyMatch);
+
+ // construct a property
+ GraphElementProperty(QString key, QString value);
+
+ // construct an atom or keymatch
+ GraphElementProperty(QString key, bool keyMatch = false);
+
+ QString key() const;
+ QString value() const;
+ void setValue(const QString &value);
+ bool atom() const;
+ bool keyMatch() const;
+
+ bool matches(const GraphElementProperty &p);
+ bool operator==(const GraphElementProperty &p);
+
+ static QString tikzEscape(QString str);
+ QString tikz();
+signals:
+
+public slots:
+
+private:
+ QString _key;
+ QString _value;
+ bool _atom;
+ bool _keyMatch;
+};
+
+#endif // GRAPHELEMENTPROPERTY_H
diff --git a/src/data/node.cpp b/src/data/node.cpp index ce4286f..44e3c77 100644 --- a/src/data/node.cpp +++ b/src/data/node.cpp @@ -1,118 +1,118 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#include "node.h" -#include "tikzit.h" - -#include <QDebug> - -Node::Node(QObject *parent) : QObject(parent), _tikzLine(-1) -{ - _data = new GraphElementData(); - _style = noneStyle; - _data->setProperty("style", "none"); -} - -Node::~Node() -{ - delete _data; -} - -Node *Node::copy() { - Node *n1 = new Node(); - n1->setName(name()); - n1->setData(data()->copy()); - n1->setPoint(point()); - n1->setLabel(label()); - n1->attachStyle(); - n1->setTikzLine(tikzLine()); - return n1; -} - -QPointF Node::point() const -{ - return _point; -} - -void Node::setPoint(const QPointF &point) -{ - _point = point; -} - -QString Node::name() const -{ - return _name; -} - -void Node::setName(const QString &name) -{ - _name = name; -} - -QString Node::label() const -{ - return _label; -} - -void Node::setLabel(const QString &label) -{ - _label = label; -} - -GraphElementData *Node::data() const -{ - return _data; -} - -void Node::setData(GraphElementData *data) -{ - delete _data; - _data = data; -} - -QString Node::styleName() const -{ - return _data->property("style"); -} - -void Node::setStyleName(const QString &styleName) -{ - _data->setProperty("style", styleName); -} - -void Node::attachStyle() -{ - QString nm = styleName(); - if (nm == "none") _style = noneStyle; - else _style = tikzit->styles()->nodeStyle(nm); -} - -NodeStyle *Node::style() const -{ - return _style; -} - -int Node::tikzLine() const -{ - return _tikzLine; -} - -void Node::setTikzLine(int tikzLine) -{ - _tikzLine = tikzLine; -} +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "node.h"
+#include "tikzit.h"
+
+#include <QDebug>
+
+Node::Node(QObject *parent) : QObject(parent), _tikzLine(-1)
+{
+ _data = new GraphElementData();
+ _style = noneStyle;
+ _data->setProperty("style", "none");
+}
+
+Node::~Node()
+{
+ delete _data;
+}
+
+Node *Node::copy() {
+ Node *n1 = new Node();
+ n1->setName(name());
+ n1->setData(data()->copy());
+ n1->setPoint(point());
+ n1->setLabel(label());
+ n1->attachStyle();
+ n1->setTikzLine(tikzLine());
+ return n1;
+}
+
+QPointF Node::point() const
+{
+ return _point;
+}
+
+void Node::setPoint(const QPointF &point)
+{
+ _point = point;
+}
+
+QString Node::name() const
+{
+ return _name;
+}
+
+void Node::setName(const QString &name)
+{
+ _name = name;
+}
+
+QString Node::label() const
+{
+ return _label;
+}
+
+void Node::setLabel(const QString &label)
+{
+ _label = label;
+}
+
+GraphElementData *Node::data() const
+{
+ return _data;
+}
+
+void Node::setData(GraphElementData *data)
+{
+ delete _data;
+ _data = data;
+}
+
+QString Node::styleName() const
+{
+ return _data->property("style");
+}
+
+void Node::setStyleName(const QString &styleName)
+{
+ _data->setProperty("style", styleName);
+}
+
+void Node::attachStyle()
+{
+ QString nm = styleName();
+ if (nm == "none") _style = noneStyle;
+ else _style = tikzit->styles()->nodeStyle(nm);
+}
+
+NodeStyle *Node::style() const
+{
+ return _style;
+}
+
+int Node::tikzLine() const
+{
+ return _tikzLine;
+}
+
+void Node::setTikzLine(int tikzLine)
+{
+ _tikzLine = tikzLine;
+}
diff --git a/src/data/node.h b/src/data/node.h index 4d4beee..2a6627e 100644 --- a/src/data/node.h +++ b/src/data/node.h @@ -1,72 +1,72 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#ifndef NODE_H -#define NODE_H - -#include "graphelementdata.h" -#include "nodestyle.h" - -#include <QObject> -#include <QPointF> -#include <QString> - -class Node : public QObject -{ - Q_OBJECT -public: - explicit Node(QObject *parent = 0); - ~Node(); - - Node *copy(); - - QPointF point() const; - void setPoint(const QPointF &point); - - QString name() const; - void setName(const QString &name); - - QString label() const; - void setLabel(const QString &label); - - GraphElementData *data() const; - void setData(GraphElementData *data); - - QString styleName() const; - void setStyleName(const QString &styleName); - - void attachStyle(); - NodeStyle *style() const; - - int tikzLine() const; - void setTikzLine(int tikzLine); - -signals: - -public slots: - -private: - QPointF _point; - QString _name; - QString _label; - NodeStyle *_style; - GraphElementData *_data; - int _tikzLine; -}; - -#endif // NODE_H +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef NODE_H
+#define NODE_H
+
+#include "graphelementdata.h"
+#include "nodestyle.h"
+
+#include <QObject>
+#include <QPointF>
+#include <QString>
+
+class Node : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Node(QObject *parent = 0);
+ ~Node();
+
+ Node *copy();
+
+ QPointF point() const;
+ void setPoint(const QPointF &point);
+
+ QString name() const;
+ void setName(const QString &name);
+
+ QString label() const;
+ void setLabel(const QString &label);
+
+ GraphElementData *data() const;
+ void setData(GraphElementData *data);
+
+ QString styleName() const;
+ void setStyleName(const QString &styleName);
+
+ void attachStyle();
+ NodeStyle *style() const;
+
+ int tikzLine() const;
+ void setTikzLine(int tikzLine);
+
+signals:
+
+public slots:
+
+private:
+ QPointF _point;
+ QString _name;
+ QString _label;
+ NodeStyle *_style;
+ GraphElementData *_data;
+ int _tikzLine;
+};
+
+#endif // NODE_H
diff --git a/src/data/nodestyle.cpp b/src/data/nodestyle.cpp index b22105c..ae9f0f7 100644 --- a/src/data/nodestyle.cpp +++ b/src/data/nodestyle.cpp @@ -1,107 +1,107 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#include "nodestyle.h" -#include <QPainter> - -NodeStyle *noneStyle = new NodeStyle(); - -NodeStyle::NodeStyle() : Style() -{ -} - - -NodeStyle::NodeStyle(QString name, GraphElementData *data): Style(name, data) -{ -} - -QColor NodeStyle::fillColor() const -{ - if (_data == 0) return Qt::white; - - QString col = propertyWithDefault("fill", "white"); - - QColor namedColor(col); - if (namedColor.isValid()) { - return namedColor; - } else { - // TODO: read RGB colors - return QColor(Qt::white); - } -} - -QBrush NodeStyle::brush() const -{ - return QBrush(fillColor()); -} - -NodeStyle::Shape NodeStyle::shape() const -{ - if (_data == 0) return NodeStyle::Circle; - - QString sh = propertyWithDefault("shape", "circle"); - if (sh == "circle") return NodeStyle::Circle; - else if (sh == "rectangle") return NodeStyle::Rectangle; - else return NodeStyle::Circle; -} - -QPainterPath NodeStyle::path() const -{ - QPainterPath pth; - pth.addEllipse(QPointF(0.0f,0.0f), 30.0f, 30.0f); - return pth; -} - -QPainterPath NodeStyle::palettePath() const -{ - return path(); -} - -QIcon NodeStyle::icon() const -{ - // draw an icon matching the style - QPixmap px(100,100); - px.fill(Qt::transparent); - QPainter painter(&px); - QPainterPath pth = path(); - pth.translate(50.0f, 50.0f); - - if (_data == 0) { - QColor c(180,180,200); - painter.setPen(QPen(c)); - painter.setBrush(QBrush(c)); - painter.drawEllipse(QPointF(50.0f,50.0f), 3,3); - - QPen pen(QColor(180,180,220)); - pen.setWidth(3); - QVector<qreal> p; - p << 2.0 << 2.0; - pen.setDashPattern(p); - painter.setPen(pen); - painter.setBrush(Qt::NoBrush); - painter.drawPath(pth); - } else { - painter.setPen(pen()); - painter.setBrush(brush()); - painter.drawPath(pth); - } - - - return QIcon(px); -} - +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "nodestyle.h"
+#include <QPainter>
+
+NodeStyle *noneStyle = new NodeStyle();
+
+NodeStyle::NodeStyle() : Style()
+{
+}
+
+
+NodeStyle::NodeStyle(QString name, GraphElementData *data): Style(name, data)
+{
+}
+
+QColor NodeStyle::fillColor() const
+{
+ if (_data == 0) return Qt::white;
+
+ QString col = propertyWithDefault("fill", "white");
+
+ QColor namedColor(col);
+ if (namedColor.isValid()) {
+ return namedColor;
+ } else {
+ // TODO: read RGB colors
+ return QColor(Qt::white);
+ }
+}
+
+QBrush NodeStyle::brush() const
+{
+ return QBrush(fillColor());
+}
+
+NodeStyle::Shape NodeStyle::shape() const
+{
+ if (_data == 0) return NodeStyle::Circle;
+
+ QString sh = propertyWithDefault("shape", "circle");
+ if (sh == "circle") return NodeStyle::Circle;
+ else if (sh == "rectangle") return NodeStyle::Rectangle;
+ else return NodeStyle::Circle;
+}
+
+QPainterPath NodeStyle::path() const
+{
+ QPainterPath pth;
+ pth.addEllipse(QPointF(0.0f,0.0f), 30.0f, 30.0f);
+ return pth;
+}
+
+QPainterPath NodeStyle::palettePath() const
+{
+ return path();
+}
+
+QIcon NodeStyle::icon() const
+{
+ // draw an icon matching the style
+ QPixmap px(100,100);
+ px.fill(Qt::transparent);
+ QPainter painter(&px);
+ QPainterPath pth = path();
+ pth.translate(50.0f, 50.0f);
+
+ if (_data == 0) {
+ QColor c(180,180,200);
+ painter.setPen(QPen(c));
+ painter.setBrush(QBrush(c));
+ painter.drawEllipse(QPointF(50.0f,50.0f), 3,3);
+
+ QPen pen(QColor(180,180,220));
+ pen.setWidth(3);
+ QVector<qreal> p;
+ p << 2.0 << 2.0;
+ pen.setDashPattern(p);
+ painter.setPen(pen);
+ painter.setBrush(Qt::NoBrush);
+ painter.drawPath(pth);
+ } else {
+ painter.setPen(pen());
+ painter.setBrush(brush());
+ painter.drawPath(pth);
+ }
+
+
+ return QIcon(px);
+}
+
diff --git a/src/data/nodestyle.h b/src/data/nodestyle.h index db38a0a..5eeef9b 100644 --- a/src/data/nodestyle.h +++ b/src/data/nodestyle.h @@ -1,51 +1,51 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#ifndef NODESTYLE_H -#define NODESTYLE_H - -#include "style.h" - -#include <QColor> -#include <QPen> -#include <QBrush> -#include <QPainterPath> -#include <QIcon> - -class NodeStyle : public Style -{ -public: - enum Shape { - Rectangle, UpTriangle, DownTriangle, Circle - }; - - NodeStyle(); - NodeStyle(QString name, GraphElementData *data); - - QColor fillColor() const; - QBrush brush() const; - QPainterPath path() const; - Shape shape() const; - - QPainterPath palettePath() const override; - QIcon icon() const override; -}; - -extern NodeStyle *noneStyle; - -#endif // NODESTYLE_H +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef NODESTYLE_H
+#define NODESTYLE_H
+
+#include "style.h"
+
+#include <QColor>
+#include <QPen>
+#include <QBrush>
+#include <QPainterPath>
+#include <QIcon>
+
+class NodeStyle : public Style
+{
+public:
+ enum Shape {
+ Rectangle, UpTriangle, DownTriangle, Circle
+ };
+
+ NodeStyle();
+ NodeStyle(QString name, GraphElementData *data);
+
+ QColor fillColor() const;
+ QBrush brush() const;
+ QPainterPath path() const;
+ Shape shape() const;
+
+ QPainterPath palettePath() const override;
+ QIcon icon() const override;
+};
+
+extern NodeStyle *noneStyle;
+
+#endif // NODESTYLE_H
diff --git a/src/data/style.cpp b/src/data/style.cpp index 2811612..41013c0 100644 --- a/src/data/style.cpp +++ b/src/data/style.cpp @@ -1,78 +1,78 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#include "style.h" - -Style::Style() : _name("none"), _data(0) -{ -} - -Style::Style(QString name, GraphElementData *data) : _name(name), _data(data) -{ -} - -bool Style::isNone() -{ - return _data == 0; -} - -GraphElementData *Style::data() const -{ - return _data; -} - -QString Style::name() const -{ - return _name; -} - -QColor Style::strokeColor() const -{ - if (_data == 0) return Qt::black; - - QString col = propertyWithDefault("draw", "black"); - - QColor namedColor(col); - if (namedColor.isValid()) { - return namedColor; - } else { - // TODO: read RGB colors - return QColor(Qt::black); - } -} - -// TODO -int Style::strokeThickness() const -{ - return 1; -} - -QPen Style::pen() const -{ - QPen p(strokeColor()); - p.setWidthF((float)strokeThickness() * 3.0f); - return p; -} - -QString Style::propertyWithDefault(QString prop, QString def) const -{ - QString val = _data->property("tikzit " + prop); - if (val.isNull()) val = _data->property(prop); - if (val.isNull()) val = def; - return val; -} +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "style.h"
+
+Style::Style() : _name("none"), _data(0)
+{
+}
+
+Style::Style(QString name, GraphElementData *data) : _name(name), _data(data)
+{
+}
+
+bool Style::isNone()
+{
+ return _data == 0;
+}
+
+GraphElementData *Style::data() const
+{
+ return _data;
+}
+
+QString Style::name() const
+{
+ return _name;
+}
+
+QColor Style::strokeColor() const
+{
+ if (_data == 0) return Qt::black;
+
+ QString col = propertyWithDefault("draw", "black");
+
+ QColor namedColor(col);
+ if (namedColor.isValid()) {
+ return namedColor;
+ } else {
+ // TODO: read RGB colors
+ return QColor(Qt::black);
+ }
+}
+
+// TODO
+int Style::strokeThickness() const
+{
+ return 1;
+}
+
+QPen Style::pen() const
+{
+ QPen p(strokeColor());
+ p.setWidthF((float)strokeThickness() * 3.0f);
+ return p;
+}
+
+QString Style::propertyWithDefault(QString prop, QString def) const
+{
+ QString val = _data->property("tikzit " + prop);
+ if (val.isNull()) val = _data->property(prop);
+ if (val.isNull()) val = def;
+ return val;
+}
diff --git a/src/data/style.h b/src/data/style.h index ac7e606..8315e5a 100644 --- a/src/data/style.h +++ b/src/data/style.h @@ -1,54 +1,54 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#ifndef STYLE_H -#define STYLE_H - - -#include "graphelementdata.h" - -#include <QColor> -#include <QPen> -#include <QBrush> -#include <QPainterPath> -#include <QIcon> - -class Style -{ -public: - Style(); - Style(QString name, GraphElementData *data); - bool isNone(); - - // properties that both edges and nodes have - GraphElementData *data() const; - QString name() const; - QColor strokeColor() const; - int strokeThickness() const; - - // methods that are implemented differently for edges and nodes - virtual QPen pen() const; - virtual QPainterPath path() const = 0; - virtual QPainterPath palettePath() const = 0; - virtual QIcon icon() const = 0; -protected: - QString propertyWithDefault(QString prop, QString def) const; - QString _name; - GraphElementData *_data; -}; -#endif // STYLE_H +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef STYLE_H
+#define STYLE_H
+
+
+#include "graphelementdata.h"
+
+#include <QColor>
+#include <QPen>
+#include <QBrush>
+#include <QPainterPath>
+#include <QIcon>
+
+class Style
+{
+public:
+ Style();
+ Style(QString name, GraphElementData *data);
+ bool isNone();
+
+ // properties that both edges and nodes have
+ GraphElementData *data() const;
+ QString name() const;
+ QColor strokeColor() const;
+ int strokeThickness() const;
+
+ // methods that are implemented differently for edges and nodes
+ virtual QPen pen() const;
+ virtual QPainterPath path() const = 0;
+ virtual QPainterPath palettePath() const = 0;
+ virtual QIcon icon() const = 0;
+protected:
+ QString propertyWithDefault(QString prop, QString def) const;
+ QString _name;
+ GraphElementData *_data;
+};
+#endif // STYLE_H
diff --git a/src/data/tikzassembler.cpp b/src/data/tikzassembler.cpp index fed3c39..cd0b517 100644 --- a/src/data/tikzassembler.cpp +++ b/src/data/tikzassembler.cpp @@ -1,72 +1,72 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#include "tikzassembler.h" - -#include "tikzparserdefs.h" -#include "tikzparser.parser.hpp" -#include "tikzlexer.h" - -int yyparse(void *scanner); - -TikzAssembler::TikzAssembler(Graph *graph, QObject *parent) : - QObject(parent), _graph(graph), _tikzStyles(0) -{ - yylex_init(&scanner); - yyset_extra(this, scanner); -} - -TikzAssembler::TikzAssembler(TikzStyles *tikzStyles, QObject *parent) : - QObject(parent), _graph(0), _tikzStyles(tikzStyles) -{ - yylex_init(&scanner); - yyset_extra(this, scanner); -} - -void TikzAssembler::addNodeToMap(Node *n) { _nodeMap.insert(n->name(), n); } -Node *TikzAssembler::nodeWithName(QString name) { return _nodeMap[name]; } - -bool TikzAssembler::parse(const QString &tikz) -{ - yy_scan_string(tikz.toLatin1().data(), scanner); - int result = yyparse(scanner); - - if (result == 0) return true; - else return false; -} - -Graph *TikzAssembler::graph() const -{ - return _graph; -} - -TikzStyles *TikzAssembler::tikzStyles() const -{ - return _tikzStyles; -} - -bool TikzAssembler::isGraph() const -{ - return _graph != 0; -} - -bool TikzAssembler::isTikzStyles() const -{ - return _tikzStyles != 0; -} - +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "tikzassembler.h"
+
+#include "tikzparserdefs.h"
+#include "tikzparser.parser.hpp"
+#include "tikzlexer.h"
+
+int yyparse(void *scanner);
+
+TikzAssembler::TikzAssembler(Graph *graph, QObject *parent) :
+ QObject(parent), _graph(graph), _tikzStyles(0)
+{
+ yylex_init(&scanner);
+ yyset_extra(this, scanner);
+}
+
+TikzAssembler::TikzAssembler(TikzStyles *tikzStyles, QObject *parent) :
+ QObject(parent), _graph(0), _tikzStyles(tikzStyles)
+{
+ yylex_init(&scanner);
+ yyset_extra(this, scanner);
+}
+
+void TikzAssembler::addNodeToMap(Node *n) { _nodeMap.insert(n->name(), n); }
+Node *TikzAssembler::nodeWithName(QString name) { return _nodeMap[name]; }
+
+bool TikzAssembler::parse(const QString &tikz)
+{
+ yy_scan_string(tikz.toLatin1().data(), scanner);
+ int result = yyparse(scanner);
+
+ if (result == 0) return true;
+ else return false;
+}
+
+Graph *TikzAssembler::graph() const
+{
+ return _graph;
+}
+
+TikzStyles *TikzAssembler::tikzStyles() const
+{
+ return _tikzStyles;
+}
+
+bool TikzAssembler::isGraph() const
+{
+ return _graph != 0;
+}
+
+bool TikzAssembler::isTikzStyles() const
+{
+ return _tikzStyles != 0;
+}
+
diff --git a/src/data/tikzassembler.h b/src/data/tikzassembler.h index f5b580c..7b32224 100644 --- a/src/data/tikzassembler.h +++ b/src/data/tikzassembler.h @@ -1,60 +1,60 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -/*! - * Convenience class to hold the parser state while loading tikz graphs or projects. - */ - -#ifndef TIKZASSEMBLER_H -#define TIKZASSEMBLER_H - -#include "node.h" -#include "graph.h" -#include "tikzstyles.h" - -#include <QObject> -#include <QHash> - -class TikzAssembler : public QObject -{ - Q_OBJECT -public: - explicit TikzAssembler(Graph *graph, QObject *parent = 0); - explicit TikzAssembler(TikzStyles *tikzStyles, QObject *parent = 0); - void addNodeToMap(Node *n); - Node *nodeWithName(QString name); - bool parse(const QString &tikz); - - Graph *graph() const; - TikzStyles *tikzStyles() const; - bool isGraph() const; - bool isTikzStyles() const; - - -signals: - -public slots: - -private: - QHash<QString,Node*> _nodeMap; - Graph *_graph; - TikzStyles *_tikzStyles; - void *scanner; -}; - -#endif // TIKZASSEMBLER_H +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+/*!
+ * Convenience class to hold the parser state while loading tikz graphs or projects.
+ */
+
+#ifndef TIKZASSEMBLER_H
+#define TIKZASSEMBLER_H
+
+#include "node.h"
+#include "graph.h"
+#include "tikzstyles.h"
+
+#include <QObject>
+#include <QHash>
+
+class TikzAssembler : public QObject
+{
+ Q_OBJECT
+public:
+ explicit TikzAssembler(Graph *graph, QObject *parent = 0);
+ explicit TikzAssembler(TikzStyles *tikzStyles, QObject *parent = 0);
+ void addNodeToMap(Node *n);
+ Node *nodeWithName(QString name);
+ bool parse(const QString &tikz);
+
+ Graph *graph() const;
+ TikzStyles *tikzStyles() const;
+ bool isGraph() const;
+ bool isTikzStyles() const;
+
+
+signals:
+
+public slots:
+
+private:
+ QHash<QString,Node*> _nodeMap;
+ Graph *_graph;
+ TikzStyles *_tikzStyles;
+ void *scanner;
+};
+
+#endif // TIKZASSEMBLER_H
diff --git a/src/data/tikzdocument.cpp b/src/data/tikzdocument.cpp index f685656..5ddec90 100644 --- a/src/data/tikzdocument.cpp +++ b/src/data/tikzdocument.cpp @@ -1,191 +1,191 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#include <QFile> -#include <QFileInfo> -#include <QSettings> -#include <QTextStream> -#include <QMessageBox> -#include <QFileDialog> - -#include "tikzit.h" -#include "tikzdocument.h" -#include "tikzassembler.h" -#include "mainwindow.h" - -TikzDocument::TikzDocument(QObject *parent) : QObject(parent) -{ - _graph = new Graph(this); - _parseSuccess = true; - _fileName = ""; - _shortName = ""; - _undoStack = new QUndoStack(); - _undoStack->setClean(); -} - -TikzDocument::~TikzDocument() -{ - delete _graph; - delete _undoStack; -} - -QUndoStack *TikzDocument::undoStack() const -{ - return _undoStack; -} - -Graph *TikzDocument::graph() const -{ - return _graph; -} - -QString TikzDocument::tikz() const -{ - return _tikz; -} - -void TikzDocument::open(QString fileName) -{ - _fileName = fileName; - QFile file(fileName); - QFileInfo fi(file); - _shortName = fi.fileName(); - QSettings settings("tikzit", "tikzit"); - settings.setValue("previous-file-path", fi.absolutePath()); - - if (!file.open(QIODevice::ReadOnly)) { -// QMessageBox::critical(this, tr("Error"), -// tr("Could not open file")); - _parseSuccess = false; - return; - } - - QTextStream in(&file); - _tikz = in.readAll(); - file.close(); - - Graph *newGraph = new Graph(this); - TikzAssembler ass(newGraph); - if (ass.parse(_tikz)) { - delete _graph; - _graph = newGraph; - foreach (Node *n, _graph->nodes()) n->attachStyle(); - foreach (Edge *e, _graph->edges()) e->updateControls(); - _parseSuccess = true; - refreshTikz(); - setClean(); - } else { - delete newGraph; - _parseSuccess = false; - } -} - -void TikzDocument::save() { - if (_fileName == "") { - saveAs(); - } else { - MainWindow *win = tikzit->activeWindow(); - if (win != 0 && !win->tikzScene()->enabled()) { - win->tikzScene()->parseTikz(win->tikzSource()); - if (!win->tikzScene()->enabled()) { - auto resp = QMessageBox::question(0, - tr("Tikz failed to parse"), - tr("Cannot save file with invalid TiKZ source. Revert changes and save?")); - if (resp == QMessageBox::Yes) win->tikzScene()->setEnabled(true); - else return; // ABORT the save - } - } - - refreshTikz(); - QFile file(_fileName); - QFileInfo fi(file); - _shortName = fi.fileName(); - QSettings settings("tikzit", "tikzit"); - settings.setValue("previous-file-path", fi.absolutePath()); - - if (file.open(QIODevice::WriteOnly)) { - QTextStream stream(&file); - stream << _tikz; - file.close(); - setClean(); - } else { - QMessageBox::warning(0, "Save Failed", "Could not open file: '" + _fileName + "' for writing."); - } - } -} - -bool TikzDocument::isClean() const -{ - return _undoStack->isClean(); -} - -void TikzDocument::setClean() -{ - _undoStack->setClean(); -} - -void TikzDocument::setGraph(Graph *graph) -{ - _graph = graph; - refreshTikz(); -} - -void TikzDocument::saveAs() { - MainWindow *win = tikzit->activeWindow(); - if (win != 0 && !win->tikzScene()->enabled()) { - win->tikzScene()->parseTikz(win->tikzSource()); - if (!win->tikzScene()->enabled()) { - auto resp = QMessageBox::question(0, - tr("Tikz failed to parse"), - tr("Cannot save file with invalid TiKZ source. Revert changes and save?")); - if (resp == QMessageBox::Yes) win->tikzScene()->setEnabled(true); - else return; // ABORT the save - } - } - - QSettings settings("tikzit", "tikzit"); - QString fileName = QFileDialog::getSaveFileName(tikzit->activeWindow(), - tr("Save File As"), - settings.value("previous-file-path").toString(), - tr("TiKZ Files (*.tikz)")); - - if (!fileName.isEmpty()) { - _fileName = fileName; - save(); - - // clean state might not change, so update title bar manually - tikzit->activeWindow()->updateFileName(); - } -} - -QString TikzDocument::shortName() const -{ - return _shortName; -} - -bool TikzDocument::parseSuccess() const -{ - return _parseSuccess; -} - -void TikzDocument::refreshTikz() -{ - _tikz = _graph->tikz(); - if (MainWindow *w = dynamic_cast<MainWindow*>(parent())) - w->refreshTikz(); -} +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include <QFile>
+#include <QFileInfo>
+#include <QSettings>
+#include <QTextStream>
+#include <QMessageBox>
+#include <QFileDialog>
+
+#include "tikzit.h"
+#include "tikzdocument.h"
+#include "tikzassembler.h"
+#include "mainwindow.h"
+
+TikzDocument::TikzDocument(QObject *parent) : QObject(parent)
+{
+ _graph = new Graph(this);
+ _parseSuccess = true;
+ _fileName = "";
+ _shortName = "";
+ _undoStack = new QUndoStack();
+ _undoStack->setClean();
+}
+
+TikzDocument::~TikzDocument()
+{
+ delete _graph;
+ delete _undoStack;
+}
+
+QUndoStack *TikzDocument::undoStack() const
+{
+ return _undoStack;
+}
+
+Graph *TikzDocument::graph() const
+{
+ return _graph;
+}
+
+QString TikzDocument::tikz() const
+{
+ return _tikz;
+}
+
+void TikzDocument::open(QString fileName)
+{
+ _fileName = fileName;
+ QFile file(fileName);
+ QFileInfo fi(file);
+ _shortName = fi.fileName();
+ QSettings settings("tikzit", "tikzit");
+ settings.setValue("previous-file-path", fi.absolutePath());
+
+ if (!file.open(QIODevice::ReadOnly)) {
+// QMessageBox::critical(this, tr("Error"),
+// tr("Could not open file"));
+ _parseSuccess = false;
+ return;
+ }
+
+ QTextStream in(&file);
+ _tikz = in.readAll();
+ file.close();
+
+ Graph *newGraph = new Graph(this);
+ TikzAssembler ass(newGraph);
+ if (ass.parse(_tikz)) {
+ delete _graph;
+ _graph = newGraph;
+ foreach (Node *n, _graph->nodes()) n->attachStyle();
+ foreach (Edge *e, _graph->edges()) e->updateControls();
+ _parseSuccess = true;
+ refreshTikz();
+ setClean();
+ } else {
+ delete newGraph;
+ _parseSuccess = false;
+ }
+}
+
+void TikzDocument::save() {
+ if (_fileName == "") {
+ saveAs();
+ } else {
+ MainWindow *win = tikzit->activeWindow();
+ if (win != 0 && !win->tikzScene()->enabled()) {
+ win->tikzScene()->parseTikz(win->tikzSource());
+ if (!win->tikzScene()->enabled()) {
+ auto resp = QMessageBox::question(0,
+ tr("Tikz failed to parse"),
+ tr("Cannot save file with invalid TiKZ source. Revert changes and save?"));
+ if (resp == QMessageBox::Yes) win->tikzScene()->setEnabled(true);
+ else return; // ABORT the save
+ }
+ }
+
+ refreshTikz();
+ QFile file(_fileName);
+ QFileInfo fi(file);
+ _shortName = fi.fileName();
+ QSettings settings("tikzit", "tikzit");
+ settings.setValue("previous-file-path", fi.absolutePath());
+
+ if (file.open(QIODevice::WriteOnly)) {
+ QTextStream stream(&file);
+ stream << _tikz;
+ file.close();
+ setClean();
+ } else {
+ QMessageBox::warning(0, "Save Failed", "Could not open file: '" + _fileName + "' for writing.");
+ }
+ }
+}
+
+bool TikzDocument::isClean() const
+{
+ return _undoStack->isClean();
+}
+
+void TikzDocument::setClean()
+{
+ _undoStack->setClean();
+}
+
+void TikzDocument::setGraph(Graph *graph)
+{
+ _graph = graph;
+ refreshTikz();
+}
+
+void TikzDocument::saveAs() {
+ MainWindow *win = tikzit->activeWindow();
+ if (win != 0 && !win->tikzScene()->enabled()) {
+ win->tikzScene()->parseTikz(win->tikzSource());
+ if (!win->tikzScene()->enabled()) {
+ auto resp = QMessageBox::question(0,
+ tr("Tikz failed to parse"),
+ tr("Cannot save file with invalid TiKZ source. Revert changes and save?"));
+ if (resp == QMessageBox::Yes) win->tikzScene()->setEnabled(true);
+ else return; // ABORT the save
+ }
+ }
+
+ QSettings settings("tikzit", "tikzit");
+ QString fileName = QFileDialog::getSaveFileName(tikzit->activeWindow(),
+ tr("Save File As"),
+ settings.value("previous-file-path").toString(),
+ tr("TiKZ Files (*.tikz)"));
+
+ if (!fileName.isEmpty()) {
+ _fileName = fileName;
+ save();
+
+ // clean state might not change, so update title bar manually
+ tikzit->activeWindow()->updateFileName();
+ }
+}
+
+QString TikzDocument::shortName() const
+{
+ return _shortName;
+}
+
+bool TikzDocument::parseSuccess() const
+{
+ return _parseSuccess;
+}
+
+void TikzDocument::refreshTikz()
+{
+ _tikz = _graph->tikz();
+ if (MainWindow *w = dynamic_cast<MainWindow*>(parent()))
+ w->refreshTikz();
+}
diff --git a/src/data/tikzdocument.h b/src/data/tikzdocument.h index 0d6b48c..773f369 100644 --- a/src/data/tikzdocument.h +++ b/src/data/tikzdocument.h @@ -1,69 +1,69 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -/*! - * This class contains a tikz Graph, source code, file info, and undo stack. It serves as the model - * in the MVC triple (TikzDocument, TikzView, TikzScene). - */ - -#ifndef TIKZDOCUMENT_H -#define TIKZDOCUMENT_H - -#include "graph.h" - -#include <QObject> -#include <QUndoStack> - -class TikzDocument : public QObject -{ - Q_OBJECT -public: - explicit TikzDocument(QObject *parent = 0); - ~TikzDocument(); - - Graph *graph() const; - void setGraph(Graph *graph); - QString tikz() const; - QUndoStack *undoStack() const; - bool parseSuccess() const; - void refreshTikz(); - - void open(QString fileName); - - QString shortName() const; - - void saveAs(); - void save(); - - bool isClean() const; - void setClean(); - -private: - Graph *_graph; - QString _tikz; - QString _fileName; - QString _shortName; - QUndoStack *_undoStack; - bool _parseSuccess; - -signals: - -public slots: -}; - -#endif // TIKZDOCUMENT_H +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+/*!
+ * This class contains a tikz Graph, source code, file info, and undo stack. It serves as the model
+ * in the MVC triple (TikzDocument, TikzView, TikzScene).
+ */
+
+#ifndef TIKZDOCUMENT_H
+#define TIKZDOCUMENT_H
+
+#include "graph.h"
+
+#include <QObject>
+#include <QUndoStack>
+
+class TikzDocument : public QObject
+{
+ Q_OBJECT
+public:
+ explicit TikzDocument(QObject *parent = 0);
+ ~TikzDocument();
+
+ Graph *graph() const;
+ void setGraph(Graph *graph);
+ QString tikz() const;
+ QUndoStack *undoStack() const;
+ bool parseSuccess() const;
+ void refreshTikz();
+
+ void open(QString fileName);
+
+ QString shortName() const;
+
+ void saveAs();
+ void save();
+
+ bool isClean() const;
+ void setClean();
+
+private:
+ Graph *_graph;
+ QString _tikz;
+ QString _fileName;
+ QString _shortName;
+ QUndoStack *_undoStack;
+ bool _parseSuccess;
+
+signals:
+
+public slots:
+};
+
+#endif // TIKZDOCUMENT_H
diff --git a/src/data/tikzlexer.l b/src/data/tikzlexer.l index 7d7e990..0a67d1d 100644 --- a/src/data/tikzlexer.l +++ b/src/data/tikzlexer.l @@ -1,191 +1,191 @@ -%{ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger, Chris Heunen, - K. Johan Paulsson, Alex Merry - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - - -/*! - * \file tikzlexer.l - * - * The lexer for tikz input. - */ - -#include "tikzparserdefs.h" -#include "tikzparser.parser.hpp" - -#include <sstream> - - -#define YY_USER_ACTION \ - yylloc->first_line = yylloc->last_line; \ - yylloc->first_column = yylloc->last_column + 1; \ - yylloc->last_column = yylloc->first_column + yyleng - 1; - -%} - -%option reentrant bison-bridge bison-locations 8bit -%option bison-locations 8bit -%option nounput -%option yylineno -%option noyywrap -%option header-file="tikzlexer.h" -%option extra-type="TikzAssembler *" - -%s props -%s xcoord -%s ycoord -%s noderef - -FLOAT \-?[0-9]*(\.[0-9]+)? - -%% - - /* whitespace is ignored, except for position counting; we don't - count formfeed and vtab as whitespace, because it's not obvious - how they should be dealt with and no-one actually uses them */ - - /* lex will take the longest-matching string */ -<INITIAL,xcoord,ycoord,props,noderef>\r\n|\r|\n { - yylloc->first_line += 1; - yylloc->last_line = yylloc->first_line; - yylloc->first_column = yylloc->last_column = 0; -} -<INITIAL,xcoord,ycoord,props,noderef>[\t ]+ { } -<INITIAL,xcoord,ycoord,props,noderef>%.*$ { } - -\\begin\{tikzpicture\} { return BEGIN_TIKZPICTURE_CMD; } -\\end\{tikzpicture\} { return END_TIKZPICTURE_CMD; } -\\tikzstyle { return TIKZSTYLE_CMD; } -\\begin\{pgfonlayer\} { return BEGIN_PGFONLAYER_CMD; } -\\end\{pgfonlayer\} { return END_PGFONLAYER_CMD; } -\\draw { return DRAW_CMD; } -\\node { return NODE_CMD; } -\\path { return PATH_CMD; } -; { return SEMICOLON; } -= { return EQUALS; } -<INITIAL>rectangle { return RECTANGLE; } -<INITIAL>node { return NODE; } -<INITIAL>at { return AT; } -<INITIAL>to { return TO; } - -\([ ]*{FLOAT}[ ]*,[ ]*{FLOAT}[ ]*\) { - yylloc->last_column = yylloc->first_column + 1; - yyless(1); - BEGIN(xcoord); -} -<xcoord>{FLOAT} { - yylval->pt = new QPointF(); - yylval->pt->setX(strtod(yytext,NULL)); - BEGIN(ycoord); -} -<ycoord>, { } -<ycoord>{FLOAT} { - yylval->pt->setY(strtod(yytext,NULL)); -} -<ycoord>\) { - BEGIN(INITIAL); - return TCOORD; -} - - /* when we see "[", change parsing mode */ -\[ /*syntaxhlfix]*/ { - BEGIN(props); - return LEFTBRACKET; -} -<props>= { return EQUALS; } -<props>, { return COMMA; } - /* technically, it is possible to have newlines in the middle of - property names or values, but in practice this is unlikely and - screws up our line counting */ -<props>[^=,\{\] \t\n]([^=,\{\]\n]*[^=,\{\] \t\n])? { - char *str = (char*)malloc(sizeof(char)*yyleng + 1); - strncpy(str, yytext, yyleng + 1); - yylval->str = str; - return PROPSTRING; -} -<props>\] { - BEGIN(INITIAL); - return RIGHTBRACKET; -} - -\( { - BEGIN(noderef); - return LEFTPARENTHESIS; -} -<noderef>\. { - return FULLSTOP; -} - /* we assume node names (and anchor names) never contain - newlines */ -<noderef>[^\.\{\)\n]+ { - //qDebug() << "nodename: " << yytext << " size: " << strlen(yytext); - char *str = (char*)malloc(sizeof(char)*yyleng + 1); - strncpy(str, yytext, yyleng+1); - yylval->str = str; - return REFSTRING; -} -<noderef>\) { - BEGIN(INITIAL); - return RIGHTPARENTHESIS; -} - -<INITIAL,props>\{ { - std::stringstream buf; - unsigned int brace_depth = 1; - unsigned int escape = 0; - while (1) { - char c = yyinput(yyscanner); - // eof reached before closing brace - if (c == '\0' || c == EOF) { - return UNCLOSED_DELIM_STR; - } - - yylloc->last_column += 1; - yyleng += 1; - if (escape) { - escape = 0; - } else if (c == '\\') { - escape = 1; - } else if (c == '{') { - brace_depth++; - } else if (c == '}') { - brace_depth--; - if (brace_depth == 0) break; - } else if (c == '\n') { - yylloc->last_line += 1; - yylloc->last_column = 0; - } - buf << c; - } - - char *str = (char*)malloc(sizeof(char) * yyleng + 1); - strncpy(str, buf.str().c_str(), yyleng + 1); - //str[len] = 0; - yylval->str = str; - //qDebug() << "got delim string: " << str; - return DELIMITEDSTRING; -} - -\\begin { return UNKNOWN_BEGIN_CMD; } -\\end { return UNKNOWN_END_CMD; } -\\[a-zA-Z0-9]+ { return UNKNOWN_CMD; } -[a-zA-Z0-9]+ { return UNKNOWN_STR; } -<INITIAL,xcoord,ycoord,props,noderef>. { return UNKNOWN_STR; } - - /* vi:ft=lex:noet:ts=4:sts=4:sw=4: - */ +%{
+/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger, Chris Heunen,
+ K. Johan Paulsson, Alex Merry
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+
+/*!
+ * \file tikzlexer.l
+ *
+ * The lexer for tikz input.
+ */
+
+#include "tikzparserdefs.h"
+#include "tikzparser.parser.hpp"
+
+#include <sstream>
+
+
+#define YY_USER_ACTION \
+ yylloc->first_line = yylloc->last_line; \
+ yylloc->first_column = yylloc->last_column + 1; \
+ yylloc->last_column = yylloc->first_column + yyleng - 1;
+
+%}
+
+%option reentrant bison-bridge bison-locations 8bit
+%option bison-locations 8bit
+%option nounput
+%option yylineno
+%option noyywrap
+%option header-file="tikzlexer.h"
+%option extra-type="TikzAssembler *"
+
+%s props
+%s xcoord
+%s ycoord
+%s noderef
+
+FLOAT \-?[0-9]*(\.[0-9]+)?
+
+%%
+
+ /* whitespace is ignored, except for position counting; we don't
+ count formfeed and vtab as whitespace, because it's not obvious
+ how they should be dealt with and no-one actually uses them */
+
+ /* lex will take the longest-matching string */
+<INITIAL,xcoord,ycoord,props,noderef>\r\n|\r|\n {
+ yylloc->first_line += 1;
+ yylloc->last_line = yylloc->first_line;
+ yylloc->first_column = yylloc->last_column = 0;
+}
+<INITIAL,xcoord,ycoord,props,noderef>[\t ]+ { }
+<INITIAL,xcoord,ycoord,props,noderef>%.*$ { }
+
+\\begin\{tikzpicture\} { return BEGIN_TIKZPICTURE_CMD; }
+\\end\{tikzpicture\} { return END_TIKZPICTURE_CMD; }
+\\tikzstyle { return TIKZSTYLE_CMD; }
+\\begin\{pgfonlayer\} { return BEGIN_PGFONLAYER_CMD; }
+\\end\{pgfonlayer\} { return END_PGFONLAYER_CMD; }
+\\draw { return DRAW_CMD; }
+\\node { return NODE_CMD; }
+\\path { return PATH_CMD; }
+; { return SEMICOLON; }
+= { return EQUALS; }
+<INITIAL>rectangle { return RECTANGLE; }
+<INITIAL>node { return NODE; }
+<INITIAL>at { return AT; }
+<INITIAL>to { return TO; }
+
+\([ ]*{FLOAT}[ ]*,[ ]*{FLOAT}[ ]*\) {
+ yylloc->last_column = yylloc->first_column + 1;
+ yyless(1);
+ BEGIN(xcoord);
+}
+<xcoord>{FLOAT} {
+ yylval->pt = new QPointF();
+ yylval->pt->setX(strtod(yytext,NULL));
+ BEGIN(ycoord);
+}
+<ycoord>, { }
+<ycoord>{FLOAT} {
+ yylval->pt->setY(strtod(yytext,NULL));
+}
+<ycoord>\) {
+ BEGIN(INITIAL);
+ return TCOORD;
+}
+
+ /* when we see "[", change parsing mode */
+\[ /*syntaxhlfix]*/ {
+ BEGIN(props);
+ return LEFTBRACKET;
+}
+<props>= { return EQUALS; }
+<props>, { return COMMA; }
+ /* technically, it is possible to have newlines in the middle of
+ property names or values, but in practice this is unlikely and
+ screws up our line counting */
+<props>[^=,\{\] \t\n]([^=,\{\]\n]*[^=,\{\] \t\n])? {
+ char *str = (char*)malloc(sizeof(char)*yyleng + 1);
+ strncpy(str, yytext, yyleng + 1);
+ yylval->str = str;
+ return PROPSTRING;
+}
+<props>\] {
+ BEGIN(INITIAL);
+ return RIGHTBRACKET;
+}
+
+\( {
+ BEGIN(noderef);
+ return LEFTPARENTHESIS;
+}
+<noderef>\. {
+ return FULLSTOP;
+}
+ /* we assume node names (and anchor names) never contain
+ newlines */
+<noderef>[^\.\{\)\n]+ {
+ //qDebug() << "nodename: " << yytext << " size: " << strlen(yytext);
+ char *str = (char*)malloc(sizeof(char)*yyleng + 1);
+ strncpy(str, yytext, yyleng+1);
+ yylval->str = str;
+ return REFSTRING;
+}
+<noderef>\) {
+ BEGIN(INITIAL);
+ return RIGHTPARENTHESIS;
+}
+
+<INITIAL,props>\{ {
+ std::stringstream buf;
+ unsigned int brace_depth = 1;
+ unsigned int escape = 0;
+ while (1) {
+ char c = yyinput(yyscanner);
+ // eof reached before closing brace
+ if (c == '\0' || c == EOF) {
+ return UNCLOSED_DELIM_STR;
+ }
+
+ yylloc->last_column += 1;
+ yyleng += 1;
+ if (escape) {
+ escape = 0;
+ } else if (c == '\\') {
+ escape = 1;
+ } else if (c == '{') {
+ brace_depth++;
+ } else if (c == '}') {
+ brace_depth--;
+ if (brace_depth == 0) break;
+ } else if (c == '\n') {
+ yylloc->last_line += 1;
+ yylloc->last_column = 0;
+ }
+ buf << c;
+ }
+
+ char *str = (char*)malloc(sizeof(char) * yyleng + 1);
+ strncpy(str, buf.str().c_str(), yyleng + 1);
+ //str[len] = 0;
+ yylval->str = str;
+ //qDebug() << "got delim string: " << str;
+ return DELIMITEDSTRING;
+}
+
+\\begin { return UNKNOWN_BEGIN_CMD; }
+\\end { return UNKNOWN_END_CMD; }
+\\[a-zA-Z0-9]+ { return UNKNOWN_CMD; }
+[a-zA-Z0-9]+ { return UNKNOWN_STR; }
+<INITIAL,xcoord,ycoord,props,noderef>. { return UNKNOWN_STR; }
+
+ /* vi:ft=lex:noet:ts=4:sts=4:sw=4:
+ */
diff --git a/src/data/tikzparser.y b/src/data/tikzparser.y index 6e708a3..3dfb66f 100644 --- a/src/data/tikzparser.y +++ b/src/data/tikzparser.y @@ -1,284 +1,284 @@ -%{ -/*! - * \file tikzparser.y - * - * The parser for tikz input. - */ - -/* - * Copyright 2010 Chris Heunen - * Copyright 2010-2017 Aleks Kissinger - * Copyright 2013 K. Johan Paulsson - * Copyright 2013 Alex Merry <dev@randomguy3.me.uk> - * - * 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, see <http://www.gnu.org/licenses/>. - */ - - -#include "tikzparserdefs.h" -%} - -/* we use features added to bison 2.4 */ -%require "2.3" - -%error-verbose -/* enable maintaining locations for better error messages */ -%locations -/* the name of the header file */ -/*%defines "common/tikzparser.h"*/ -/* make it re-entrant (no global variables) */ -%pure-parser -/* We use a pure (re-entrant) lexer. This means yylex - will take a void* (opaque) type to maintain its state */ -%lex-param {void *scanner} -/* Since this parser is also pure, yyparse needs to take - that lexer state as an argument */ -%parse-param {void *scanner} - -/* possible data types for semantic values */ -%union { - char *str; - GraphElementProperty *prop; - GraphElementData *data; - Node *node; - QPointF *pt; - struct noderef noderef; -} - -%{ -#include "node.h" -#include "edge.h" -#include "graphelementdata.h" -#include "graphelementproperty.h" - -#include "tikzlexer.h" -#include "tikzassembler.h" -/* the assembler (used by this parser) is stored in the lexer - state as "extra" data */ -#define assembler yyget_extra(scanner) - -/* pass errors off to the assembler */ -void yyerror(YYLTYPE *yylloc, void *scanner, const char *str) { - // TODO: implement reportError() - //assembler->reportError(str, yylloc); - qDebug() << "\nparse error: " << str << " line:" << yylloc->first_line; -} -%} - -/* yyloc is set up with first_column = last_column = 1 by default; - however, it makes more sense to think of us being "before the - start of the line" before we parse anything */ -%initial-action { - yylloc.first_column = yylloc.last_column = 0; -} - - -%token BEGIN_TIKZPICTURE_CMD "\\begin{tikzpicture}" -%token END_TIKZPICTURE_CMD "\\end{tikzpicture}" -%token TIKZSTYLE_CMD "\\tikzstyle" -%token BEGIN_PGFONLAYER_CMD "\\begin{pgfonlayer}" -%token END_PGFONLAYER_CMD "\\end{pgfonlayer}" -%token DRAW_CMD "\\draw" -%token NODE_CMD "\\node" -%token PATH_CMD "\\path" -%token RECTANGLE "rectangle" -%token NODE "node" -%token AT "at" -%token TO "to" -%token SEMICOLON ";" -%token COMMA "," - -%token LEFTPARENTHESIS "(" -%token RIGHTPARENTHESIS ")" -%token LEFTBRACKET "[" -%token RIGHTBRACKET "]" -%token FULLSTOP "." -%token EQUALS "=" -%token <pt> TCOORD "coordinate" -%token <str> PROPSTRING "key/value string" -%token <str> REFSTRING "string" -%token <str> DELIMITEDSTRING "{-delimited string" - -%token UNKNOWN_BEGIN_CMD "unknown \\begin command" -%token UNKNOWN_END_CMD "unknown \\end command" -%token UNKNOWN_CMD "unknown latex command" -%token UNKNOWN_STR "unknown string" -%token UNCLOSED_DELIM_STR "unclosed {-delimited string" - -%type<str> nodename -%type<str> optanchor -%type<str> val -%type<prop> property -%type<data> extraproperties -%type<data> properties -%type<data> optproperties -%type<node> optedgenode -%type<noderef> noderef -%type<noderef> optnoderef - -%% - - -tikz: tikzstyles | tikzpicture; - -tikzstyles: tikzstyles tikzstyle | ; -tikzstyle: "\\tikzstyle" DELIMITEDSTRING "=" "[" properties "]" - { - if (assembler->isTikzStyles()) { - assembler->tikzStyles()->addStyle(QString($2), $5); - } - } - -tikzpicture: "\\begin{tikzpicture}" optproperties tikzcmds "\\end{tikzpicture}" - { - if (assembler->isGraph() && $2) { - assembler->graph()->setData($2); - } - }; -tikzcmds: tikzcmds tikzcmd | ; -tikzcmd: node | edge | boundingbox | ignore; - -ignore: "\\begin{pgfonlayer}" DELIMITEDSTRING | "\\end{pgfonlayer}"; - -optproperties: - "[" "]" - { $$ = 0; } - | "[" properties "]" - { $$ = $2; } - | { $$ = 0; }; -properties: extraproperties property - { - $1->add(*$2); - delete $2; - $$ = $1; - }; -extraproperties: - extraproperties property "," - { - $1->add(*$2); - delete $2; - $$ = $1; - } - | { $$ = new GraphElementData(); }; -property: - val "=" val - { - GraphElementProperty *p = new GraphElementProperty(QString($1),QString($3)); - free($1); - free($3); - $$ = p; - } - | val - { - GraphElementProperty *a = new GraphElementProperty(QString($1)); - free($1); - $$ = a; - }; -val: PROPSTRING { $$ = $1; } | DELIMITEDSTRING { $$ = $1; }; - -nodename: "(" REFSTRING ")" { $$ = $2; }; -node: "\\node" optproperties nodename "at" TCOORD DELIMITEDSTRING ";" - { - Node *node = new Node(); - - if ($2) { - node->setData($2); - } - //qDebug() << "node name: " << $3; - node->setName(QString($3)); - node->setLabel(QString($6)); - free($3); - free($6); - - node->setPoint(*$5); - delete $5; - - assembler->graph()->addNode(node); - assembler->addNodeToMap(node); - }; - -optanchor: { $$ = 0; } | "." REFSTRING { $$ = $2; }; -noderef: "(" REFSTRING optanchor ")" - { - $$.node = assembler->nodeWithName(QString($2)); - free($2); - $$.anchor = $3; - }; -optnoderef: - noderef { $$ = $1; } - | "(" ")" { $$.node = 0; $$.anchor = 0; } -optedgenode: - { $$ = 0; } - | "node" optproperties DELIMITEDSTRING - { - $$ = new Node(); - if ($2) - $$->setData($2); - $$->setLabel(QString($3)); - free($3); - } -edge: "\\draw" optproperties noderef "to" optedgenode optnoderef ";" - { - Node *s; - Node *t; - - s = $3.node; - - if ($6.node) { - t = $6.node; - } else { - t = s; - } - - // 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 ($5) - edge->setEdgeNode($5); - if ($3.anchor) { - edge->setSourceAnchor(QString($3.anchor)); - free($3.anchor); - } - - if ($6.node) { - if ($6.anchor) { - edge->setTargetAnchor(QString($6.anchor)); - free($6.anchor); - } - } else { - edge->setTargetAnchor(edge->sourceAnchor()); - } - - assembler->graph()->addEdge(edge); - } - }; - -ignoreprop: val | val "=" val; -ignoreprops: ignoreprop ignoreprops | ; -optignoreprops: "[" ignoreprops "]"; -boundingbox: - "\\path" optignoreprops TCOORD "rectangle" TCOORD ";" - { - assembler->graph()->setBbox(QRectF(*$3, *$5)); - delete $3; - delete $5; - }; - -/* vi:ft=yacc:noet:ts=4:sts=4:sw=4 -*/ +%{
+/*!
+ * \file tikzparser.y
+ *
+ * The parser for tikz input.
+ */
+
+/*
+ * Copyright 2010 Chris Heunen
+ * Copyright 2010-2017 Aleks Kissinger
+ * Copyright 2013 K. Johan Paulsson
+ * Copyright 2013 Alex Merry <dev@randomguy3.me.uk>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "tikzparserdefs.h"
+%}
+
+/* we use features added to bison 2.4 */
+%require "2.3"
+
+%error-verbose
+/* enable maintaining locations for better error messages */
+%locations
+/* the name of the header file */
+/*%defines "common/tikzparser.h"*/
+/* make it re-entrant (no global variables) */
+%pure-parser
+/* We use a pure (re-entrant) lexer. This means yylex
+ will take a void* (opaque) type to maintain its state */
+%lex-param {void *scanner}
+/* Since this parser is also pure, yyparse needs to take
+ that lexer state as an argument */
+%parse-param {void *scanner}
+
+/* possible data types for semantic values */
+%union {
+ char *str;
+ GraphElementProperty *prop;
+ GraphElementData *data;
+ Node *node;
+ QPointF *pt;
+ struct noderef noderef;
+}
+
+%{
+#include "node.h"
+#include "edge.h"
+#include "graphelementdata.h"
+#include "graphelementproperty.h"
+
+#include "tikzlexer.h"
+#include "tikzassembler.h"
+/* the assembler (used by this parser) is stored in the lexer
+ state as "extra" data */
+#define assembler yyget_extra(scanner)
+
+/* pass errors off to the assembler */
+void yyerror(YYLTYPE *yylloc, void *scanner, const char *str) {
+ // TODO: implement reportError()
+ //assembler->reportError(str, yylloc);
+ qDebug() << "\nparse error: " << str << " line:" << yylloc->first_line;
+}
+%}
+
+/* yyloc is set up with first_column = last_column = 1 by default;
+ however, it makes more sense to think of us being "before the
+ start of the line" before we parse anything */
+%initial-action {
+ yylloc.first_column = yylloc.last_column = 0;
+}
+
+
+%token BEGIN_TIKZPICTURE_CMD "\\begin{tikzpicture}"
+%token END_TIKZPICTURE_CMD "\\end{tikzpicture}"
+%token TIKZSTYLE_CMD "\\tikzstyle"
+%token BEGIN_PGFONLAYER_CMD "\\begin{pgfonlayer}"
+%token END_PGFONLAYER_CMD "\\end{pgfonlayer}"
+%token DRAW_CMD "\\draw"
+%token NODE_CMD "\\node"
+%token PATH_CMD "\\path"
+%token RECTANGLE "rectangle"
+%token NODE "node"
+%token AT "at"
+%token TO "to"
+%token SEMICOLON ";"
+%token COMMA ","
+
+%token LEFTPARENTHESIS "("
+%token RIGHTPARENTHESIS ")"
+%token LEFTBRACKET "["
+%token RIGHTBRACKET "]"
+%token FULLSTOP "."
+%token EQUALS "="
+%token <pt> TCOORD "coordinate"
+%token <str> PROPSTRING "key/value string"
+%token <str> REFSTRING "string"
+%token <str> DELIMITEDSTRING "{-delimited string"
+
+%token UNKNOWN_BEGIN_CMD "unknown \\begin command"
+%token UNKNOWN_END_CMD "unknown \\end command"
+%token UNKNOWN_CMD "unknown latex command"
+%token UNKNOWN_STR "unknown string"
+%token UNCLOSED_DELIM_STR "unclosed {-delimited string"
+
+%type<str> nodename
+%type<str> optanchor
+%type<str> val
+%type<prop> property
+%type<data> extraproperties
+%type<data> properties
+%type<data> optproperties
+%type<node> optedgenode
+%type<noderef> noderef
+%type<noderef> optnoderef
+
+%%
+
+
+tikz: tikzstyles | tikzpicture;
+
+tikzstyles: tikzstyles tikzstyle | ;
+tikzstyle: "\\tikzstyle" DELIMITEDSTRING "=" "[" properties "]"
+ {
+ if (assembler->isTikzStyles()) {
+ assembler->tikzStyles()->addStyle(QString($2), $5);
+ }
+ }
+
+tikzpicture: "\\begin{tikzpicture}" optproperties tikzcmds "\\end{tikzpicture}"
+ {
+ if (assembler->isGraph() && $2) {
+ assembler->graph()->setData($2);
+ }
+ };
+tikzcmds: tikzcmds tikzcmd | ;
+tikzcmd: node | edge | boundingbox | ignore;
+
+ignore: "\\begin{pgfonlayer}" DELIMITEDSTRING | "\\end{pgfonlayer}";
+
+optproperties:
+ "[" "]"
+ { $$ = 0; }
+ | "[" properties "]"
+ { $$ = $2; }
+ | { $$ = 0; };
+properties: extraproperties property
+ {
+ $1->add(*$2);
+ delete $2;
+ $$ = $1;
+ };
+extraproperties:
+ extraproperties property ","
+ {
+ $1->add(*$2);
+ delete $2;
+ $$ = $1;
+ }
+ | { $$ = new GraphElementData(); };
+property:
+ val "=" val
+ {
+ GraphElementProperty *p = new GraphElementProperty(QString($1),QString($3));
+ free($1);
+ free($3);
+ $$ = p;
+ }
+ | val
+ {
+ GraphElementProperty *a = new GraphElementProperty(QString($1));
+ free($1);
+ $$ = a;
+ };
+val: PROPSTRING { $$ = $1; } | DELIMITEDSTRING { $$ = $1; };
+
+nodename: "(" REFSTRING ")" { $$ = $2; };
+node: "\\node" optproperties nodename "at" TCOORD DELIMITEDSTRING ";"
+ {
+ Node *node = new Node();
+
+ if ($2) {
+ node->setData($2);
+ }
+ //qDebug() << "node name: " << $3;
+ node->setName(QString($3));
+ node->setLabel(QString($6));
+ free($3);
+ free($6);
+
+ node->setPoint(*$5);
+ delete $5;
+
+ assembler->graph()->addNode(node);
+ assembler->addNodeToMap(node);
+ };
+
+optanchor: { $$ = 0; } | "." REFSTRING { $$ = $2; };
+noderef: "(" REFSTRING optanchor ")"
+ {
+ $$.node = assembler->nodeWithName(QString($2));
+ free($2);
+ $$.anchor = $3;
+ };
+optnoderef:
+ noderef { $$ = $1; }
+ | "(" ")" { $$.node = 0; $$.anchor = 0; }
+optedgenode:
+ { $$ = 0; }
+ | "node" optproperties DELIMITEDSTRING
+ {
+ $$ = new Node();
+ if ($2)
+ $$->setData($2);
+ $$->setLabel(QString($3));
+ free($3);
+ }
+edge: "\\draw" optproperties noderef "to" optedgenode optnoderef ";"
+ {
+ Node *s;
+ Node *t;
+
+ s = $3.node;
+
+ if ($6.node) {
+ t = $6.node;
+ } else {
+ t = s;
+ }
+
+ // 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 ($5)
+ edge->setEdgeNode($5);
+ if ($3.anchor) {
+ edge->setSourceAnchor(QString($3.anchor));
+ free($3.anchor);
+ }
+
+ if ($6.node) {
+ if ($6.anchor) {
+ edge->setTargetAnchor(QString($6.anchor));
+ free($6.anchor);
+ }
+ } else {
+ edge->setTargetAnchor(edge->sourceAnchor());
+ }
+
+ assembler->graph()->addEdge(edge);
+ }
+ };
+
+ignoreprop: val | val "=" val;
+ignoreprops: ignoreprop ignoreprops | ;
+optignoreprops: "[" ignoreprops "]";
+boundingbox:
+ "\\path" optignoreprops TCOORD "rectangle" TCOORD ";"
+ {
+ assembler->graph()->setBbox(QRectF(*$3, *$5));
+ delete $3;
+ delete $5;
+ };
+
+/* vi:ft=yacc:noet:ts=4:sts=4:sw=4
+*/
diff --git a/src/data/tikzparserdefs.h b/src/data/tikzparserdefs.h index a5e77be..02743fe 100644 --- a/src/data/tikzparserdefs.h +++ b/src/data/tikzparserdefs.h @@ -1,40 +1,40 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#ifndef TIKZPARSERDEFS_H -#define TIKZPARSERDEFS_H - -#define YY_NO_UNISTD_H 1 - -#include "graphelementproperty.h" -#include "graphelementdata.h" -#include "node.h" -#include "tikzassembler.h" - -#include <QString> -#include <QRectF> -#include <QDebug> - -struct noderef { - Node *node; - char *anchor; -}; - -inline int isatty(int) { return 0; } - -#endif // TIKZPARSERDEFS_H +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef TIKZPARSERDEFS_H
+#define TIKZPARSERDEFS_H
+
+#define YY_NO_UNISTD_H 1
+
+#include "graphelementproperty.h"
+#include "graphelementdata.h"
+#include "node.h"
+#include "tikzassembler.h"
+
+#include <QString>
+#include <QRectF>
+#include <QDebug>
+
+struct noderef {
+ Node *node;
+ char *anchor;
+};
+
+inline int isatty(int) { return 0; }
+
+#endif // TIKZPARSERDEFS_H
diff --git a/src/data/tikzstyles.cpp b/src/data/tikzstyles.cpp index a924c01..addd464 100644 --- a/src/data/tikzstyles.cpp +++ b/src/data/tikzstyles.cpp @@ -1,71 +1,71 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#include "tikzstyles.h" -#include "nodestyle.h" - -#include <QDebug> - -TikzStyles::TikzStyles(QObject *parent) : QObject(parent) -{ - -} - -NodeStyle *TikzStyles::nodeStyle(QString name) const -{ - foreach (NodeStyle *s , _nodeStyles) - if (s->name() == name) return s; - return noneStyle; -} - -EdgeStyle *TikzStyles::edgeStyle(QString name) const -{ - foreach (EdgeStyle *s , _edgeStyles) - if (s->name() == name) return s; - return noneEdgeStyle; -} - -QVector<NodeStyle *> TikzStyles::nodeStyles() const -{ - return _nodeStyles; -} - -void TikzStyles::clear() -{ - _nodeStyles.clear(); - _edgeStyles.clear(); -} - -QVector<EdgeStyle *> TikzStyles::edgeStyles() const -{ - return _edgeStyles; -} - -void TikzStyles::addStyle(QString name, GraphElementData *data) -{ - if (data->atom("-") || data->atom("->") || data->atom("-|") || - data->atom("<-") || data->atom("<->") || data->atom("<-|") || - data->atom("|-") || data->atom("|->") || data->atom("|-|")) - { // edge style - qDebug() << "got edge style" << name; - _edgeStyles << new EdgeStyle(name, data); - } else { // node style - qDebug() << "got node style" << name; - _nodeStyles << new NodeStyle(name, data); - } -} +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "tikzstyles.h"
+#include "nodestyle.h"
+
+#include <QDebug>
+
+TikzStyles::TikzStyles(QObject *parent) : QObject(parent)
+{
+
+}
+
+NodeStyle *TikzStyles::nodeStyle(QString name) const
+{
+ foreach (NodeStyle *s , _nodeStyles)
+ if (s->name() == name) return s;
+ return noneStyle;
+}
+
+EdgeStyle *TikzStyles::edgeStyle(QString name) const
+{
+ foreach (EdgeStyle *s , _edgeStyles)
+ if (s->name() == name) return s;
+ return noneEdgeStyle;
+}
+
+QVector<NodeStyle *> TikzStyles::nodeStyles() const
+{
+ return _nodeStyles;
+}
+
+void TikzStyles::clear()
+{
+ _nodeStyles.clear();
+ _edgeStyles.clear();
+}
+
+QVector<EdgeStyle *> TikzStyles::edgeStyles() const
+{
+ return _edgeStyles;
+}
+
+void TikzStyles::addStyle(QString name, GraphElementData *data)
+{
+ if (data->atom("-") || data->atom("->") || data->atom("-|") ||
+ data->atom("<-") || data->atom("<->") || data->atom("<-|") ||
+ data->atom("|-") || data->atom("|->") || data->atom("|-|"))
+ { // edge style
+ qDebug() << "got edge style" << name;
+ _edgeStyles << new EdgeStyle(name, data);
+ } else { // node style
+ qDebug() << "got node style" << name;
+ _nodeStyles << new NodeStyle(name, data);
+ }
+}
diff --git a/src/data/tikzstyles.h b/src/data/tikzstyles.h index 0f7cce1..da9a05f 100644 --- a/src/data/tikzstyles.h +++ b/src/data/tikzstyles.h @@ -1,51 +1,51 @@ -/* - TikZiT - a GUI diagram editor for TikZ - Copyright (C) 2018 Aleks Kissinger - - 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 3 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, see <https://www.gnu.org/licenses/>. -*/ - -#ifndef PROJECT_H -#define PROJECT_H - -#include "graphelementdata.h" -#include "nodestyle.h" -#include "edgestyle.h" - -#include <QObject> -#include <QString> - -class TikzStyles : public QObject -{ - Q_OBJECT -public: - explicit TikzStyles(QObject *parent = 0); - void addStyle(QString name, GraphElementData *data); - - NodeStyle *nodeStyle(QString name) const; - EdgeStyle *edgeStyle(QString name) const; - QVector<NodeStyle *> nodeStyles() const; - QVector<EdgeStyle *> edgeStyles() const; - void clear(); - -signals: - -public slots: - -private: - QVector<NodeStyle*> _nodeStyles; - QVector<EdgeStyle*> _edgeStyles; -}; - -#endif // PROJECT_H +/*
+ TikZiT - a GUI diagram editor for TikZ
+ Copyright (C) 2018 Aleks Kissinger
+
+ 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 3 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, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef PROJECT_H
+#define PROJECT_H
+
+#include "graphelementdata.h"
+#include "nodestyle.h"
+#include "edgestyle.h"
+
+#include <QObject>
+#include <QString>
+
+class TikzStyles : public QObject
+{
+ Q_OBJECT
+public:
+ explicit TikzStyles(QObject *parent = 0);
+ void addStyle(QString name, GraphElementData *data);
+
+ NodeStyle *nodeStyle(QString name) const;
+ EdgeStyle *edgeStyle(QString name) const;
+ QVector<NodeStyle *> nodeStyles() const;
+ QVector<EdgeStyle *> edgeStyles() const;
+ void clear();
+
+signals:
+
+public slots:
+
+private:
+ QVector<NodeStyle*> _nodeStyles;
+ QVector<EdgeStyle*> _edgeStyles;
+};
+
+#endif // PROJECT_H
|