diff options
Diffstat (limited to 'src/data')
-rw-r--r-- | src/data/edge.cpp | 22 | ||||
-rw-r--r-- | src/data/edge.h | 1 | ||||
-rw-r--r-- | src/data/graph.cpp | 82 | ||||
-rw-r--r-- | src/data/graph.h | 25 | ||||
-rw-r--r-- | src/data/graphelementdata.cpp | 17 | ||||
-rw-r--r-- | src/data/graphelementdata.h | 6 | ||||
-rw-r--r-- | src/data/node.cpp | 35 | ||||
-rw-r--r-- | src/data/node.h | 7 | ||||
-rw-r--r-- | src/data/nodestyle.cpp | 10 | ||||
-rw-r--r-- | src/data/nodestyle.h | 10 | ||||
-rw-r--r-- | src/data/tikzdocument.cpp | 45 | ||||
-rw-r--r-- | src/data/tikzdocument.h | 3 |
12 files changed, 239 insertions, 24 deletions
diff --git a/src/data/edge.cpp b/src/data/edge.cpp index e4d5d69..d3396e8 100644 --- a/src/data/edge.cpp +++ b/src/data/edge.cpp @@ -25,6 +25,28 @@ Edge::~Edge() 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->updateControls(); + return e; +} + Node *Edge::source() const { return _source; diff --git a/src/data/edge.h b/src/data/edge.h index 595b094..f010acd 100644 --- a/src/data/edge.h +++ b/src/data/edge.h @@ -13,6 +13,7 @@ class Edge : public QObject public: explicit Edge(Node *s, Node *t, QObject *parent = 0); ~Edge(); + Edge *copy(QMap<Node *, Node *> *nodeTable = 0); Node *source() const; Node *target() const; diff --git a/src/data/graph.cpp b/src/data/graph.cpp index ba9a4c6..7a5fedc 100644 --- a/src/data/graph.cpp +++ b/src/data/graph.cpp @@ -54,6 +54,32 @@ void Graph::removeEdge(Edge *e) _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; +} + +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; @@ -92,21 +118,27 @@ 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()) + 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()) @@ -115,17 +147,23 @@ QString Graph::tikz() code << "(" << n->name() << ") at (" << n->point().x() << ", " << n->point().y() << ") {" << n->label() << "};\n"; + line++; } - if (!_nodes.isEmpty()) + if (!_nodes.isEmpty()) { code << "\t\\end{pgfonlayer}\n"; + line++; + } - if (!_edges.isEmpty()) + if (!_edges.isEmpty()) { code << "\t\\begin{pgfonlayer}{edgelayer}\n"; + line++; + } Edge *e; foreach (e, _edges) { + e->updateData(); code << "\t\t\\draw "; if (!e->data()->isEmpty()) @@ -153,17 +191,53 @@ QString Graph::tikz() } code << ";\n"; + line++; } - if (!_edges.isEmpty()) + 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()) { + Node *n1 = n->copy(); + nodeTable.insert(n, n1); + addNode(n1); + } + foreach (Edge *e, graph->edges()) { + addEdge(e->copy(&nodeTable)); + } +} + void Graph::setBbox(const QRectF &bbox) { _bbox = bbox; diff --git a/src/data/graph.h b/src/data/graph.h index c25d51b..4d575e4 100644 --- a/src/data/graph.h +++ b/src/data/graph.h @@ -27,6 +27,15 @@ public: 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); @@ -40,6 +49,22 @@ public: void clearBbox(); 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 a copy of the given graph. Prior to calling this + * method, the node names in the given graph should be made fresh via + * "renameApart". + * \param graph + */ + void insertGraph(Graph *graph); signals: public slots: diff --git a/src/data/graphelementdata.cpp b/src/data/graphelementdata.cpp index 43f7516..63c8cea 100644 --- a/src/data/graphelementdata.cpp +++ b/src/data/graphelementdata.cpp @@ -3,9 +3,14 @@ #include <QDebug> #include <QTextStream> -GraphElementData::GraphElementData(QObject *parent) : QAbstractItemModel(parent) +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() @@ -13,6 +18,11 @@ GraphElementData::~GraphElementData() delete root; } +GraphElementData *GraphElementData::copy() +{ + return new GraphElementData(_properties); +} + void GraphElementData::setProperty(QString key, QString value) { GraphElementProperty m(key, true); @@ -170,3 +180,8 @@ 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 0d43bb8..319edf7 100644 --- a/src/data/graphelementdata.h +++ b/src/data/graphelementdata.h @@ -13,8 +13,11 @@ 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); @@ -22,7 +25,6 @@ public: 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; @@ -55,6 +57,8 @@ public: QString tikz(); bool isEmpty(); + QVector<GraphElementProperty> properties() const; + signals: public slots: diff --git a/src/data/node.cpp b/src/data/node.cpp index c78f49c..085bdf5 100644 --- a/src/data/node.cpp +++ b/src/data/node.cpp @@ -3,11 +3,11 @@ #include <QDebug> -Node::Node(QObject *parent) : QObject(parent) +Node::Node(QObject *parent) : QObject(parent), _tikzLine(-1) { _data = new GraphElementData(); _style = noneStyle; - _styleName = "none"; + _data->setProperty("style", "none"); } Node::~Node() @@ -15,6 +15,17 @@ 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; @@ -54,26 +65,36 @@ void Node::setData(GraphElementData *data) { delete _data; _data = data; - if (_data->property("style") != 0) _styleName = _data->property("style"); } QString Node::styleName() const { - return _styleName; + return _data->property("style"); } void Node::setStyleName(const QString &styleName) { - _styleName = styleName; + _data->setProperty("style", styleName); } void Node::attachStyle() { - if (_styleName == "none") _style = noneStyle; - else _style = tikzit->styles()->nodeStyle(_styleName); + 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 ee70835..241d1ca 100644 --- a/src/data/node.h +++ b/src/data/node.h @@ -15,6 +15,8 @@ public: explicit Node(QObject *parent = 0); ~Node(); + Node *copy(); + QPointF point() const; void setPoint(const QPointF &point); @@ -33,6 +35,9 @@ public: void attachStyle(); NodeStyle *style() const; + int tikzLine() const; + void setTikzLine(int tikzLine); + signals: public slots: @@ -41,9 +46,9 @@ private: QPointF _point; QString _name; QString _label; - QString _styleName; NodeStyle *_style; GraphElementData *_data; + int _tikzLine; }; #endif // NODE_H diff --git a/src/data/nodestyle.cpp b/src/data/nodestyle.cpp index e38d3a3..302ab84 100644 --- a/src/data/nodestyle.cpp +++ b/src/data/nodestyle.cpp @@ -24,13 +24,13 @@ QString NodeStyle::name() const return _name; } -NodeShape NodeStyle::shape() const +NodeStyle::Shape NodeStyle::shape() const { QString sh = _data->property("shape"); - if (sh.isNull()) return NodeShape::Circle; - else if (sh == "circle") return NodeShape::Circle; - else if (sh == "rectangle") return NodeShape::Rectangle; - else return NodeShape::Circle; + if (sh.isNull()) return NodeStyle::Circle; + else if (sh == "circle") return NodeStyle::Circle; + else if (sh == "rectangle") return NodeStyle::Rectangle; + else return NodeStyle::Circle; } QColor NodeStyle::fillColor() const diff --git a/src/data/nodestyle.h b/src/data/nodestyle.h index 58c0c12..0b9f282 100644 --- a/src/data/nodestyle.h +++ b/src/data/nodestyle.h @@ -9,20 +9,20 @@ #include <QPainterPath> #include <QIcon> -enum NodeShape { - Rectangle, UpTriangle, DownTriangle, Circle -}; - class NodeStyle { public: + enum Shape { + Rectangle, UpTriangle, DownTriangle, Circle + }; + NodeStyle(); NodeStyle(QString name, GraphElementData *data); bool isNone(); GraphElementData *data() const; QString name() const; - NodeShape shape() const; + Shape shape() const; QColor fillColor() const; QColor strokeColor() const; int strokeThickness() const; diff --git a/src/data/tikzdocument.cpp b/src/data/tikzdocument.cpp index a3fa961..eeb4e14 100644 --- a/src/data/tikzdocument.cpp +++ b/src/data/tikzdocument.cpp @@ -3,9 +3,12 @@ #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) { @@ -71,6 +74,41 @@ void TikzDocument::open(QString fileName) } } +void TikzDocument::save() { + if (_fileName == "") { + saveAs(); + } else { + 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::ReadWrite)) { + QTextStream stream(&file); + stream << _tikz; + file.close(); + tikzit->activeWindow()->updateFileName(); + } else { + QMessageBox::warning(0, "Save Failed", "Could not open file: '" + _fileName + "' for writing."); + } + } +} + +void TikzDocument::saveAs() { + 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(); + } +} + QString TikzDocument::shortName() const { return _shortName; @@ -80,3 +118,10 @@ 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 d3a18b1..edb1beb 100644 --- a/src/data/tikzdocument.h +++ b/src/data/tikzdocument.h @@ -22,11 +22,14 @@ public: QString tikz() const; QUndoStack *undoStack() const; bool parseSuccess() const; + void refreshTikz(); void open(QString fileName); QString shortName() const; + void saveAs(); + void save(); private: Graph *_graph; QString _tikz; |