summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleks Kissinger <aleks0@gmail.com>2017-12-27 23:27:20 +0000
committerAleks Kissinger <aleks0@gmail.com>2017-12-27 23:27:20 +0000
commitc63dd506beefa844ddeab587a71af94063357372 (patch)
treeaed5f5d1e6c0cca3866bec6fa1818b2fc8f883d7
parentfcc0fc080370c0c8e97a0c07043b83240d973cab (diff)
adding and deleting nodes now works
-rw-r--r--tikzit/src/data/edge.cpp4
-rw-r--r--tikzit/src/data/graph.cpp43
-rw-r--r--tikzit/src/data/graph.h10
-rw-r--r--tikzit/src/data/node.cpp7
-rw-r--r--tikzit/src/data/node.h4
-rw-r--r--tikzit/src/data/nodestyle.cpp2
-rw-r--r--tikzit/src/data/nodestyle.h2
-rw-r--r--tikzit/src/gui/nodeitem.cpp10
-rw-r--r--tikzit/src/gui/nodeitem.h2
-rw-r--r--tikzit/src/gui/tikzscene.cpp65
-rw-r--r--tikzit/src/gui/tikzscene.h20
-rw-r--r--tikzit/src/gui/undocommands.cpp79
-rw-r--r--tikzit/src/gui/undocommands.h32
-rw-r--r--tikzit/src/tikzit.cpp35
-rw-r--r--tikzit/src/tikzit.h4
15 files changed, 232 insertions, 87 deletions
diff --git a/tikzit/src/data/edge.cpp b/tikzit/src/data/edge.cpp
index 3ff6c6e..6802b2d 100644
--- a/tikzit/src/data/edge.cpp
+++ b/tikzit/src/data/edge.cpp
@@ -117,14 +117,14 @@ void Edge::updateControls() {
}
// TODO: calculate head and tail properly, not just for circles
- if (_source->style().isNone()) {
+ if (_source->style()->isNone()) {
_tail = src;
} else {
_tail = QPointF(src.x() + std::cos(outAngleR) * 0.1,
src.y() + std::sin(outAngleR) * 0.1);
}
- if (_target->style().isNone()) {
+ if (_target->style()->isNone()) {
_head = targ;
} else {
_head = QPointF(targ.x() + std::cos(inAngleR) * 0.1,
diff --git a/tikzit/src/data/graph.cpp b/tikzit/src/data/graph.cpp
index 4329928..ba9a4c6 100644
--- a/tikzit/src/data/graph.cpp
+++ b/tikzit/src/data/graph.cpp
@@ -1,6 +1,10 @@
#include "graph.h"
#include <QTextStream>
+#include <QSet>
+#include <QtAlgorithms>
+#include <QDebug>
+#include <algorithm>
Graph::Graph(QObject *parent) : QObject(parent)
{
@@ -12,30 +16,42 @@ 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.removeAll(n);
- inEdges.remove(n);
- outEdges.remove(n);
+ _nodes.removeOne(n);
}
-Edge *Graph::addEdge(Edge *e)
+
+void Graph::addEdge(Edge *e)
{
e->setParent(this);
_edges << e;
- outEdges.insert(e->source(), e);
- inEdges.insert(e->target(), e);
- return 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.removeAll(e);
- outEdges.remove(e->source(), e);
- inEdges.remove(e->target(), e);
+ _edges.removeOne(e);
}
GraphElementData *Graph::data() const
@@ -153,11 +169,4 @@ void Graph::setBbox(const QRectF &bbox)
_bbox = bbox;
}
-// add a node. The graph claims ownership.
-Node *Graph::addNode(Node *n) {
- n->setParent(this);
- _nodes << n;
- return n;
-}
-
diff --git a/tikzit/src/data/graph.h b/tikzit/src/data/graph.h
index 963def8..8856e5c 100644
--- a/tikzit/src/data/graph.h
+++ b/tikzit/src/data/graph.h
@@ -21,9 +21,11 @@ class Graph : public QObject
public:
explicit Graph(QObject *parent = 0);
~Graph();
- Node *addNode(Node *n);
+ void addNode(Node *n);
+ void addNode(Node *n, int index);
void removeNode(Node *n);
- Edge *addEdge(Edge *e);
+ void addEdge(Edge *e);
+ void addEdge(Edge *e, int index);
void removeEdge(Edge *e);
GraphElementData *data() const;
@@ -45,8 +47,8 @@ public slots:
private:
QVector<Node*> _nodes;
QVector<Edge*> _edges;
- QMultiHash<Node*,Edge*> inEdges;
- QMultiHash<Node*,Edge*> outEdges;
+ //QMultiHash<Node*,Edge*> inEdges;
+ //QMultiHash<Node*,Edge*> outEdges;
GraphElementData *_data;
QRectF _bbox;
};
diff --git a/tikzit/src/data/node.cpp b/tikzit/src/data/node.cpp
index 1b8ccf8..f94a3df 100644
--- a/tikzit/src/data/node.cpp
+++ b/tikzit/src/data/node.cpp
@@ -6,7 +6,7 @@
Node::Node(QObject *parent) : QObject(parent)
{
_data = new GraphElementData();
- _style = NodeStyle();
+ _style = noneStyle;
_styleName = "none";
}
@@ -69,12 +69,11 @@ void Node::setStyleName(const QString &styleName)
void Node::attachStyle()
{
- if (_styleName == "none") _style = NodeStyle();
+ if (_styleName == "none") _style = noneStyle;
else _style = tikzit->nodeStyle(_styleName);
}
-NodeStyle Node::style() const
+NodeStyle *Node::style() const
{
return _style;
}
-
diff --git a/tikzit/src/data/node.h b/tikzit/src/data/node.h
index 91b1725..ee70835 100644
--- a/tikzit/src/data/node.h
+++ b/tikzit/src/data/node.h
@@ -31,7 +31,7 @@ public:
void setStyleName(const QString &styleName);
void attachStyle();
- NodeStyle style() const;
+ NodeStyle *style() const;
signals:
@@ -42,7 +42,7 @@ private:
QString _name;
QString _label;
QString _styleName;
- NodeStyle _style;
+ NodeStyle *_style;
GraphElementData *_data;
};
diff --git a/tikzit/src/data/nodestyle.cpp b/tikzit/src/data/nodestyle.cpp
index 109e2af..7eca791 100644
--- a/tikzit/src/data/nodestyle.cpp
+++ b/tikzit/src/data/nodestyle.cpp
@@ -1,5 +1,7 @@
#include "nodestyle.h"
+NodeStyle *noneStyle = new NodeStyle();
+
NodeStyle::NodeStyle()
{
name = "none";
diff --git a/tikzit/src/data/nodestyle.h b/tikzit/src/data/nodestyle.h
index baf967c..00d1b20 100644
--- a/tikzit/src/data/nodestyle.h
+++ b/tikzit/src/data/nodestyle.h
@@ -21,6 +21,6 @@ public:
int strokeThickness;
};
-extern NodeStyle noneStyle;
+extern NodeStyle *noneStyle;
#endif // NODESTYLE_H
diff --git a/tikzit/src/gui/nodeitem.cpp b/tikzit/src/gui/nodeitem.cpp
index 40b4de9..71226f3 100644
--- a/tikzit/src/gui/nodeitem.cpp
+++ b/tikzit/src/gui/nodeitem.cpp
@@ -41,9 +41,9 @@ QRectF NodeItem::labelRect() const {
return rect;
}
-void NodeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+void NodeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
- if (_node->style().isNone()) {
+ if (_node->style()->isNone()) {
QColor c(180,180,200);
painter->setPen(QPen(c));
painter->setBrush(QBrush(c));
@@ -57,10 +57,10 @@ void NodeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
painter->setBrush(Qt::NoBrush);
painter->drawPath(shape());
} else {
- QPen pen(_node->style().strokeColor);
- pen.setWidth(_node->style().strokeThickness);
+ QPen pen(_node->style()->strokeColor);
+ pen.setWidth(_node->style()->strokeThickness);
painter->setPen(pen);
- painter->setBrush(QBrush(_node->style().fillColor));
+ painter->setBrush(QBrush(_node->style()->fillColor));
painter->drawPath(shape());
}
diff --git a/tikzit/src/gui/nodeitem.h b/tikzit/src/gui/nodeitem.h
index d0f1e62..9a3edb0 100644
--- a/tikzit/src/gui/nodeitem.h
+++ b/tikzit/src/gui/nodeitem.h
@@ -18,7 +18,7 @@ public:
NodeItem(Node *node);
void readPos();
void writePos();
- void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *);
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
QPainterPath shape() const;
QRectF boundingRect() const;
diff --git a/tikzit/src/gui/tikzscene.cpp b/tikzit/src/gui/tikzscene.cpp
index a900192..2d9b49f 100644
--- a/tikzit/src/gui/tikzscene.cpp
+++ b/tikzit/src/gui/tikzscene.cpp
@@ -17,7 +17,7 @@ TikzScene::TikzScene(TikzDocument *tikzDocument, QObject *parent) :
TikzScene::~TikzScene() {
}
-Graph *TikzScene::graph() const
+Graph *TikzScene::graph()
{
return _tikzDocument->graph();
}
@@ -38,13 +38,13 @@ void TikzScene::graphReplaced()
foreach (Edge *e, graph()->edges()) {
EdgeItem *ei = new EdgeItem(e);
- _edgeItems << ei;
+ _edgeItems.insert(e, ei);
addItem(ei);
}
foreach (Node *n, graph()->nodes()) {
NodeItem *ni = new NodeItem(n);
- _nodeItems << ni;
+ _nodeItems.insert(n, ni);
addItem(ni);
}
}
@@ -267,7 +267,14 @@ void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
break;
case ToolPalette::VERTEX:
- // TODO
+ {
+ int gridSize = GLOBAL_SCALE / 8;
+ QPointF gridPos(round(mousePos.x()/gridSize)*gridSize, round(mousePos.y()/gridSize)*gridSize);
+ Node *n = new Node();
+ n->setPoint(fromScreen(gridPos));
+ AddNodeCommand *cmd = new AddNodeCommand(this, n);
+ _tikzDocument->undoStack()->push(cmd);
+ }
break;
case ToolPalette::EDGE:
break;
@@ -276,6 +283,44 @@ void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
}
}
+void TikzScene::keyReleaseEvent(QKeyEvent *event)
+{
+ if (event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete) {
+ QSet<Node*> selNodes;
+ QSet<Edge*> selEdges;
+ getSelection(selNodes, selEdges);
+
+ QMap<int,Node*> deleteNodes;
+ QMap<int,Edge*> deleteEdges;
+
+ for (int i = 0; i < _tikzDocument->graph()->nodes().length(); ++i) {
+ Node *n = _tikzDocument->graph()->nodes()[i];
+ if (selNodes.contains(n)) deleteNodes.insert(i, n);
+ }
+
+ for (int i = 0; i < _tikzDocument->graph()->edges().length(); ++i) {
+ Edge *e = _tikzDocument->graph()->edges()[i];
+ if (selEdges.contains(e) ||
+ selNodes.contains(e->source()) ||
+ selNodes.contains(e->target())) deleteEdges.insert(i, e);
+ }
+
+ //qDebug() << "nodes:" << deleteNodes;
+ //qDebug() << "edges:" << deleteEdges;
+ DeleteCommand *cmd = new DeleteCommand(this, deleteNodes, deleteEdges, selEdges);
+ _tikzDocument->undoStack()->push(cmd);
+ }
+}
+
+void TikzScene::getSelection(QSet<Node *> &selNodes, QSet<Edge *> &selEdges)
+{
+ foreach (QGraphicsItem *gi, selectedItems()) {
+ if (NodeItem *ni = dynamic_cast<NodeItem*>(gi)) selNodes << ni->node();
+ if (EdgeItem *ei = dynamic_cast<EdgeItem*>(gi)) selEdges << ei->edge();
+ }
+}
+
+
TikzDocument *TikzScene::tikzDocument() const
{
return _tikzDocument;
@@ -287,11 +332,6 @@ void TikzScene::setTikzDocument(TikzDocument *tikzDocument)
graphReplaced();
}
-QVector<EdgeItem *> TikzScene::edgeItems() const
-{
- return _edgeItems;
-}
-
void TikzScene::refreshAdjacentEdges(QList<Node*> nodes)
{
if (nodes.empty()) return;
@@ -303,7 +343,12 @@ void TikzScene::refreshAdjacentEdges(QList<Node*> nodes)
}
}
-QVector<NodeItem *> TikzScene::nodeItems() const
+QMap<Node*,NodeItem *> &TikzScene::nodeItems()
{
return _nodeItems;
}
+
+QMap<Edge*,EdgeItem*> &TikzScene::edgeItems()
+{
+ return _edgeItems;
+}
diff --git a/tikzit/src/gui/tikzscene.h b/tikzit/src/gui/tikzscene.h
index db95d88..a9af34b 100644
--- a/tikzit/src/gui/tikzscene.h
+++ b/tikzit/src/gui/tikzscene.h
@@ -25,9 +25,9 @@ class TikzScene : public QGraphicsScene
public:
TikzScene(TikzDocument *tikzDocument, QObject *parent);
~TikzScene();
- Graph *graph() const;
- QVector<NodeItem *> nodeItems() const;
- QVector<EdgeItem *> edgeItems() const;
+ Graph *graph();
+ QMap<Node*,NodeItem*> &nodeItems();
+ QMap<Edge*,EdgeItem*> &edgeItems();
void refreshAdjacentEdges(QList<Node*> nodes);
TikzDocument *tikzDocument() const;
@@ -35,14 +35,16 @@ public:
public slots:
void graphReplaced();
+
protected:
- void mousePressEvent(QGraphicsSceneMouseEvent *event);
- void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
- void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+ void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
+ void keyReleaseEvent(QKeyEvent *event) override;
private:
TikzDocument *_tikzDocument;
- QVector<NodeItem*> _nodeItems;
- QVector<EdgeItem*> _edgeItems;
+ QMap<Node*,NodeItem*> _nodeItems;
+ QMap<Edge*,EdgeItem*> _edgeItems;
EdgeItem *_modifyEdgeItem;
bool _firstControlPoint;
@@ -51,6 +53,8 @@ private:
int _oldBend;
int _oldInAngle;
int _oldOutAngle;
+
+ void getSelection(QSet<Node*> &selNodes, QSet<Edge*> &selEdges);
};
#endif // TIKZSCENE_H
diff --git a/tikzit/src/gui/undocommands.cpp b/tikzit/src/gui/undocommands.cpp
index 54741c8..997bf75 100644
--- a/tikzit/src/gui/undocommands.cpp
+++ b/tikzit/src/gui/undocommands.cpp
@@ -1,4 +1,6 @@
#include "undocommands.h"
+#include "nodeitem.h"
+#include "edgeitem.h"
MoveCommand::MoveCommand(TikzScene *scene,
QMap<Node*, QPointF> oldNodePositions,
@@ -8,8 +10,7 @@ MoveCommand::MoveCommand(TikzScene *scene,
_scene(scene),
_oldNodePositions(oldNodePositions),
_newNodePositions(newNodePositions)
-{
-}
+{}
void MoveCommand::undo()
@@ -78,3 +79,77 @@ void EdgeBendCommand::redo()
}
}
}
+
+DeleteCommand::DeleteCommand(TikzScene *scene,
+ QMap<int, Node *> deleteNodes,
+ QMap<int, Edge *> deleteEdges,
+ QSet<Edge *> selEdges) :
+ _scene(scene), _deleteNodes(deleteNodes),
+ _deleteEdges(deleteEdges), _selEdges(selEdges)
+{}
+
+void DeleteCommand::undo()
+{
+ for (auto it = _deleteNodes.begin(); it != _deleteNodes.end(); ++it) {
+ Node *n = it.value();
+ _scene->graph()->addNode(n, it.key());
+ NodeItem *ni = new NodeItem(n);
+ _scene->nodeItems().insert(n, ni);
+ _scene->addItem(ni);
+ ni->setSelected(true);
+ }
+
+ for (auto it = _deleteEdges.begin(); it != _deleteEdges.end(); ++it) {
+ Edge *e = it.value();
+ _scene->graph()->addEdge(e, it.key());
+ EdgeItem *ei = new EdgeItem(e);
+ _scene->edgeItems().insert(e, ei);
+ _scene->addItem(ei);
+
+ if (_selEdges.contains(e)) ei->setSelected(true);
+ }
+}
+
+void DeleteCommand::redo()
+{
+ foreach (Edge *e, _deleteEdges.values()) {
+ EdgeItem *ei = _scene->edgeItems()[e];
+ _scene->edgeItems().remove(e);
+ _scene->removeItem(ei);
+ delete ei;
+
+ _scene->graph()->removeEdge(e);
+ }
+
+ foreach (Node *n, _deleteNodes.values()) {
+ NodeItem *ni = _scene->nodeItems()[n];
+ _scene->nodeItems().remove(n);
+ _scene->removeItem(ni);
+ delete ni;
+
+ _scene->graph()->removeNode(n);
+ }
+}
+
+AddNodeCommand::AddNodeCommand(TikzScene *scene, Node *node) :
+ _scene(scene), _node(node)
+{}
+
+void AddNodeCommand::undo()
+{
+ NodeItem *ni = _scene->nodeItems()[_node];
+ _scene->removeItem(ni);
+ _scene->nodeItems().remove(_node);
+ delete ni;
+
+ _scene->graph()->removeNode(_node);
+}
+
+void AddNodeCommand::redo()
+{
+ // TODO: get the current style
+ _scene->graph()->addNode(_node);
+ NodeItem *ni = new NodeItem(_node);
+ _scene->nodeItems().insert(_node, ni);
+ _scene->addItem(ni);
+}
diff --git a/tikzit/src/gui/undocommands.h b/tikzit/src/gui/undocommands.h
index bb6a8e9..c1b4910 100644
--- a/tikzit/src/gui/undocommands.h
+++ b/tikzit/src/gui/undocommands.h
@@ -1,5 +1,8 @@
/**
- * These classes store the data required to undo/redo a single UI action.
+ * All changes to a TikzDocument are done via subclasses of QUndoCommand. When a controller
+ * (e.g. TikzScene) gets input from the user to change the document, it will push one of
+ * these commands onto the TikzDocument's undo stack, which automatically calls the redo()
+ * method of the command.
*/
#ifndef UNDOCOMMANDS_H
@@ -45,4 +48,31 @@ private:
int _newOutAngle;
};
+class DeleteCommand : public QUndoCommand
+{
+public:
+ explicit DeleteCommand(TikzScene *scene,
+ QMap<int,Node*> deleteNodes,
+ QMap<int,Edge*> deleteEdges,
+ QSet<Edge*> selEdges);
+ void undo() override;
+ void redo() override;
+private:
+ TikzScene *_scene;
+ QMap<int,Node*> _deleteNodes;
+ QMap<int,Edge*> _deleteEdges;
+ QSet<Edge*> _selEdges;
+};
+
+class AddNodeCommand : public QUndoCommand
+{
+public:
+ explicit AddNodeCommand(TikzScene *scene, Node *node);
+ void undo() override;
+ void redo() override;
+private:
+ TikzScene *_scene;
+ Node *_node;
+};
+
#endif // UNDOCOMMANDS_H
diff --git a/tikzit/src/tikzit.cpp b/tikzit/src/tikzit.cpp
index 94fc644..42d16e8 100644
--- a/tikzit/src/tikzit.cpp
+++ b/tikzit/src/tikzit.cpp
@@ -43,32 +43,11 @@ PropertyPalette *Tikzit::propertyPalette() const
return _propertyPalette;
}
-//void Tikzit::createMenu()
-//{
-// _mainMenu = new QMenuBar(0);
-// QMenu *file = _mainMenu->addMenu(tr("&File"));
-// QAction *aNew = file->addAction(tr("&New"));
-// aNew->setShortcut(QKeySequence::New);
-// QAction *aOpen = file->addAction(tr("&Open"));
-// aOpen->setShortcut(QKeySequence::Open);
-
-// QMenu *view = _mainMenu->addMenu(tr("&View"));
-// QAction *aZoomIn = view->addAction(tr("Zoom &In"));
-// aZoomIn->setShortcut(QKeySequence::ZoomIn);
-// QAction *aZoomOut = view->addAction(tr("Zoom &Out"));
-// aZoomOut->setShortcut(QKeySequence::ZoomOut);
-
-// connect(aNew, SIGNAL(triggered()), this, SLOT(newDoc()));
-// connect(aOpen, SIGNAL(triggered()), this, SLOT(open()));
-// connect(aZoomIn, SIGNAL(triggered()), this, SLOT(zoomIn()));
-// connect(aZoomOut, SIGNAL(triggered()), this, SLOT(zoomOut()));
-//}
-
void Tikzit::loadStyles()
{
- _nodeStyles << NodeStyle("black dot", NodeShape::Circle, Qt::black, Qt::black, 1);
- _nodeStyles << NodeStyle("white dot", NodeShape::Circle, Qt::white, Qt::black, 1);
- _nodeStyles << NodeStyle("gray dot", NodeShape::Circle, Qt::gray, Qt::black, 1);
+ _nodeStyles << new NodeStyle("black dot", NodeShape::Circle, Qt::black, Qt::black, 1);
+ _nodeStyles << new NodeStyle("white dot", NodeShape::Circle, Qt::white, Qt::black, 1);
+ _nodeStyles << new NodeStyle("gray dot", NodeShape::Circle, Qt::gray, Qt::black, 1);
}
void Tikzit::newDoc()
@@ -97,11 +76,11 @@ void Tikzit::removeWindow(MainWindow *w)
}
}
-NodeStyle Tikzit::nodeStyle(QString name)
+NodeStyle *Tikzit::nodeStyle(QString name)
{
- foreach (NodeStyle s , _nodeStyles)
- if (s.name == name) return s;
- return NodeStyle(name, NodeShape::Circle, Qt::white);
+ foreach (NodeStyle *s , _nodeStyles)
+ if (s->name == name) return s;
+ return noneStyle; //NodeStyle(name, NodeShape::Circle, Qt::white);
}
void Tikzit::open()
diff --git a/tikzit/src/tikzit.h b/tikzit/src/tikzit.h
index bf4f7f1..deb683e 100644
--- a/tikzit/src/tikzit.h
+++ b/tikzit/src/tikzit.h
@@ -43,7 +43,7 @@ public:
MainWindow *activeWindow() const;
void setActiveWindow(MainWindow *activeWindow);
void removeWindow(MainWindow *w);
- NodeStyle nodeStyle(QString name);
+ NodeStyle *nodeStyle(QString name);
static QFont LABEL_FONT;
// Ui::MainMenu *_mainMenuUi;
@@ -61,7 +61,7 @@ private:
PropertyPalette *_propertyPalette;
QVector<MainWindow*> _windows;
MainWindow *_activeWindow;
- QVector<NodeStyle> _nodeStyles;
+ QVector<NodeStyle*> _nodeStyles;
};