diff options
author | Aleks Kissinger <aleks0@gmail.com> | 2018-03-17 19:01:02 -0400 |
---|---|---|
committer | Aleks Kissinger <aleks0@gmail.com> | 2018-03-17 19:01:02 -0400 |
commit | 3cea1514203a451c0a8806d276807863b463a78f (patch) | |
tree | d6850ab0f41a6d85f3504e8c92fcecf79b37689b /src/gui | |
parent | 39c2c74c664a6c770639ead8f45322352cacb997 (diff) |
added saving, style application, and copy and paste
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/mainmenu.cpp | 21 | ||||
-rw-r--r-- | src/gui/mainwindow.cpp | 23 | ||||
-rw-r--r-- | src/gui/mainwindow.h | 8 | ||||
-rw-r--r-- | src/gui/nodeitem.cpp | 4 | ||||
-rw-r--r-- | src/gui/tikzscene.cpp | 176 | ||||
-rw-r--r-- | src/gui/tikzscene.h | 10 | ||||
-rw-r--r-- | src/gui/toolpalette.cpp | 18 | ||||
-rw-r--r-- | src/gui/toolpalette.h | 1 | ||||
-rw-r--r-- | src/gui/undocommands.cpp | 147 | ||||
-rw-r--r-- | src/gui/undocommands.h | 63 |
10 files changed, 391 insertions, 80 deletions
diff --git a/src/gui/mainmenu.cpp b/src/gui/mainmenu.cpp index 714ed34..dfb447f 100644 --- a/src/gui/mainmenu.cpp +++ b/src/gui/mainmenu.cpp @@ -19,17 +19,20 @@ void MainMenu::on_actionOpen_triggered() void MainMenu::on_actionClose_triggered() { - // TODO + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->close(); } void MainMenu::on_actionSave_triggered() { - // TODO + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzDocument()->save(); } void MainMenu::on_actionSave_As_triggered() { - // TODO + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzDocument()->saveAs(); } void MainMenu::on_actionExit_triggered() @@ -53,22 +56,26 @@ void MainMenu::on_actionRedo_triggered() void MainMenu::on_actionCut_triggered() { - // TODO + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzScene()->cutToClipboard(); } void MainMenu::on_actionCopy_triggered() { - // TODO + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzScene()->copyToClipboard(); } void MainMenu::on_actionPaste_triggered() { - // TODO + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzScene()->pasteFromClipboard(); } void MainMenu::on_actionDelete_triggered() { - // TODO + if (tikzit->activeWindow() != 0) + tikzit->activeWindow()->tikzScene()->deleteSelectedItems(); } void MainMenu::on_actionSelect_All_triggered() diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index eac7c44..26e19b6 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -25,12 +25,11 @@ MainWindow::MainWindow(QWidget *parent) : setAttribute(Qt::WA_DeleteOnClose, true); _tikzDocument = new TikzDocument(this); - _tools = new ToolPalette(this); - addToolBar(_tools); + _toolPalette = new ToolPalette(this); + addToolBar(_toolPalette); - _tikzScene = new TikzScene(_tikzDocument, _tools, this); + _tikzScene = new TikzScene(_tikzDocument, _toolPalette, this); ui->tikzView->setScene(_tikzScene); - _fileName = ""; _pristine = true; @@ -80,10 +79,26 @@ void MainWindow::changeEvent(QEvent *event) { if (event->type() == QEvent::ActivationChange && isActiveWindow()) { tikzit->setActiveWindow(this); + tikzit->stylePalette()->raise(); } QMainWindow::changeEvent(event); } +void MainWindow::updateFileName() +{ + setWindowTitle("TiKZiT - " + _tikzDocument->shortName()); +} + +void MainWindow::refreshTikz() +{ + ui->tikzSource->setText(_tikzDocument->tikz()); +} + +ToolPalette *MainWindow::toolPalette() const +{ + return _toolPalette; +} + TikzDocument *MainWindow::tikzDocument() const { return _tikzDocument; diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index ba680b0..613bfcb 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -33,17 +33,19 @@ public: TikzView *tikzView() const; TikzScene *tikzScene() const; TikzDocument *tikzDocument() const; - + ToolPalette *toolPalette() const; + void updateFileName(); + void refreshTikz(); protected: void closeEvent(QCloseEvent *event); void changeEvent(QEvent *event); + private: TikzScene *_tikzScene; TikzDocument *_tikzDocument; MainMenu *_menu; - ToolPalette *_tools; + ToolPalette *_toolPalette; Ui::MainWindow *ui; - QString _fileName; bool _pristine; int _windowId; static int _numWindows; diff --git a/src/gui/nodeitem.cpp b/src/gui/nodeitem.cpp index 21cdf79..36d488c 100644 --- a/src/gui/nodeitem.cpp +++ b/src/gui/nodeitem.cpp @@ -15,8 +15,8 @@ NodeItem::NodeItem(Node *node) { _node = node; setFlag(QGraphicsItem::ItemIsSelectable); - setFlag(QGraphicsItem::ItemIsMovable); - setFlag(QGraphicsItem::ItemSendsGeometryChanges); + //setFlag(QGraphicsItem::ItemIsMovable); + //setFlag(QGraphicsItem::ItemSendsGeometryChanges); readPos(); } diff --git a/src/gui/tikzscene.cpp b/src/gui/tikzscene.cpp index a3dd8ce..2ee3c50 100644 --- a/src/gui/tikzscene.cpp +++ b/src/gui/tikzscene.cpp @@ -2,10 +2,12 @@ #include "util.h" #include "tikzscene.h" #include "undocommands.h" +#include "tikzassembler.h" #include <QPen> #include <QBrush> #include <QDebug> +#include <QClipboard> TikzScene::TikzScene(TikzDocument *tikzDocument, ToolPalette *tools, QObject *parent) : @@ -63,7 +65,9 @@ void TikzScene::graphReplaced() void TikzScene::mousePressEvent(QGraphicsSceneMouseEvent *event) { // current mouse position, in scene coordinates - QPointF mousePos = event->scenePos(); + _mouseDownPos = event->scenePos(); + + _draggingNodes = false; // disable rubber band drag, which will clear the selection. Only re-enable it // for the SELECT tool, and when no control point has been clicked. @@ -80,8 +84,8 @@ void TikzScene::mousePressEvent(QGraphicsSceneMouseEvent *event) if (EdgeItem *ei = dynamic_cast<EdgeItem*>(gi)) { qreal dx, dy; - dx = ei->cp1Item()->pos().x() - mousePos.x(); - dy = ei->cp1Item()->pos().y() - mousePos.y(); + dx = ei->cp1Item()->pos().x() - _mouseDownPos.x(); + dy = ei->cp1Item()->pos().y() - _mouseDownPos.y(); if (dx*dx + dy*dy <= cpR2) { _modifyEdgeItem = ei; @@ -89,8 +93,8 @@ void TikzScene::mousePressEvent(QGraphicsSceneMouseEvent *event) break; } - dx = ei->cp2Item()->pos().x() - mousePos.x(); - dy = ei->cp2Item()->pos().y() - mousePos.y(); + dx = ei->cp2Item()->pos().x() - _mouseDownPos.x(); + dy = ei->cp2Item()->pos().y() - _mouseDownPos.y(); if (dx*dx + dy*dy <= cpR2) { _modifyEdgeItem = ei; @@ -119,17 +123,21 @@ void TikzScene::mousePressEvent(QGraphicsSceneMouseEvent *event) _oldNodePositions.insert(ni->node(), ni->node()->point()); } } + + auto its = items(_mouseDownPos); + if (!its.isEmpty() && dynamic_cast<NodeItem*>(its[0])) + _draggingNodes = true; } break; case ToolPalette::VERTEX: break; case ToolPalette::EDGE: - foreach (QGraphicsItem *gi, items(mousePos)) { + foreach (QGraphicsItem *gi, items(_mouseDownPos)) { if (NodeItem *ni = dynamic_cast<NodeItem*>(gi)){ _edgeStartNodeItem = ni; _edgeEndNodeItem = ni; - QLineF line(toScreen(ni->node()->point()), mousePos); + QLineF line(toScreen(ni->node()->point()), _mouseDownPos); _drawEdgeItem->setLine(line); _drawEdgeItem->setVisible(true); break; @@ -145,8 +153,9 @@ void TikzScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { // current mouse position, in scene coordinates QPointF mousePos = event->scenePos(); - QRectF rb = views()[0]->rubberBandRect(); - invalidate(-800,-800,1600,1600); + //QRectF rb = views()[0]->rubberBandRect(); + //invalidate(-800,-800,1600,1600); + invalidate(QRectF(), QGraphicsScene::BackgroundLayer); switch (_tools->currentTool()) { case ToolPalette::SELECT: @@ -229,10 +238,25 @@ void TikzScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) _modifyEdgeItem->readPos(); + } else if (_draggingNodes) { // nodes being dragged + QGraphicsScene::mouseMoveEvent(event); + + // apply the same offset to all nodes, otherwise we get odd rounding behaviour with + // multiple selection. + QPointF shift = mousePos - _mouseDownPos; + int gridSize = GLOBAL_SCALE / 8; + shift = QPointF(round(shift.x()/gridSize)*gridSize, round(shift.y()/gridSize)*gridSize); + + foreach (Node *n, _oldNodePositions.keys()) { + NodeItem *ni = _nodeItems[n]; + ni->setPos(toScreen(_oldNodePositions[n]) + shift); + ni->writePos(); + } + + refreshAdjacentEdges(_oldNodePositions.keys()); } else { // otherwise, process mouse move normally QGraphicsScene::mouseMoveEvent(event); - refreshAdjacentEdges(_oldNodePositions.keys()); } break; @@ -308,7 +332,9 @@ void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) int gridSize = GLOBAL_SCALE / 8; QPointF gridPos(round(mousePos.x()/gridSize)*gridSize, round(mousePos.y()/gridSize)*gridSize); Node *n = new Node(_tikzDocument); + n->setName(graph()->freshNodeName()); n->setPoint(fromScreen(gridPos)); + n->setStyleName(tikzit->stylePalette()->activeNodeStyleName()); QRectF grow(gridPos.x() - GLOBAL_SCALEF, gridPos.y() - GLOBAL_SCALEF, 2 * GLOBAL_SCALEF, 2 * GLOBAL_SCALEF); QRectF newBounds = sceneRect().united(grow); @@ -332,34 +358,31 @@ void TikzScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) case ToolPalette::CROP: break; } + + // clear artefacts from rubber band selection + invalidate(QRect(), QGraphicsScene::BackgroundLayer); } 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); + deleteSelectedItems(); + } else if (event->modifiers() == Qt::NoModifier) { + switch(event->key()) { + case Qt::Key_S: + tikzit->activeWindow()->toolPalette()->setCurrentTool(ToolPalette::SELECT); + break; + case Qt::Key_V: + case Qt::Key_N: + tikzit->activeWindow()->toolPalette()->setCurrentTool(ToolPalette::VERTEX); + break; + case Qt::Key_E: + tikzit->activeWindow()->toolPalette()->setCurrentTool(ToolPalette::EDGE); + break; + case Qt::Key_B: + tikzit->activeWindow()->toolPalette()->setCurrentTool(ToolPalette::CROP); + break; } - - //qDebug() << "nodes:" << deleteNodes; - //qDebug() << "edges:" << deleteEdges; - DeleteCommand *cmd = new DeleteCommand(this, deleteNodes, deleteEdges, selEdges); - _tikzDocument->undoStack()->push(cmd); } } @@ -375,6 +398,78 @@ void TikzScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) } } +void TikzScene::applyActiveStyleToNodes() { + ApplyStyleToNodesCommand *cmd = new ApplyStyleToNodesCommand(this, tikzit->stylePalette()->activeNodeStyleName()); + _tikzDocument->undoStack()->push(cmd); +} + +void TikzScene::deleteSelectedItems() +{ + 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::copyToClipboard() +{ + Graph *g = graph()->copyOfSubgraphWithNodes(getSelectedNodes()); + QGuiApplication::clipboard()->setText(g->tikz()); + delete g; +} + +void TikzScene::cutToClipboard() +{ + copyToClipboard(); + deleteSelectedItems(); +} + + +void TikzScene::pasteFromClipboard() +{ + QString tikz = QGuiApplication::clipboard()->text(); + Graph *g = new Graph(); + TikzAssembler ass(g); + + // attempt to parse whatever's on the clipboard, if we get a + // non-empty tikz graph, insert it. + if (ass.parse(tikz) && !g->nodes().isEmpty()) { + // make sure names in the new subgraph are fresh + g->renameApart(graph()); + + // shift g to the right until there is some free space + QPointF p0 = toScreen(g->nodes()[0]->point()); + QPointF p = p0; + while (!items(p).isEmpty()) p.setX(p.x()+GLOBAL_SCALEF); + QPointF shift(roundf((p.x() - p0.x())/GLOBAL_SCALEF), 0.0f); + foreach (Node *n, g->nodes()) { + n->setPoint(n->point() + shift); + } + + PasteCommand *cmd = new PasteCommand(this, g); + _tikzDocument->undoStack()->push(cmd); + } +} + void TikzScene::getSelection(QSet<Node *> &selNodes, QSet<Edge *> &selEdges) { foreach (QGraphicsItem *gi, selectedItems()) { @@ -383,6 +478,15 @@ void TikzScene::getSelection(QSet<Node *> &selNodes, QSet<Edge *> &selEdges) } } +QSet<Node *> TikzScene::getSelectedNodes() +{ + QSet<Node*> selNodes; + foreach (QGraphicsItem *gi, selectedItems()) { + if (NodeItem *ni = dynamic_cast<NodeItem*>(gi)) selNodes << ni->node(); + } + return selNodes; +} + TikzDocument *TikzScene::tikzDocument() const { @@ -395,6 +499,14 @@ void TikzScene::setTikzDocument(TikzDocument *tikzDocument) graphReplaced(); } +void TikzScene::reloadStyles() +{ + foreach (NodeItem *ni, _nodeItems) { + ni->node()->attachStyle(); + ni->readPos(); // trigger a repaint + } +} + void TikzScene::refreshAdjacentEdges(QList<Node*> nodes) { if (nodes.empty()) return; diff --git a/src/gui/tikzscene.h b/src/gui/tikzscene.h index cb684b2..5d3eec2 100644 --- a/src/gui/tikzscene.h +++ b/src/gui/tikzscene.h @@ -34,7 +34,12 @@ public: TikzDocument *tikzDocument() const; void setTikzDocument(TikzDocument *tikzDocument); - + void reloadStyles(); + void applyActiveStyleToNodes(); + void deleteSelectedItems(); + void copyToClipboard(); + void cutToClipboard(); + void pasteFromClipboard(); public slots: void graphReplaced(); @@ -54,6 +59,8 @@ private: NodeItem *_edgeStartNodeItem; NodeItem *_edgeEndNodeItem; bool _firstControlPoint; + QPointF _mouseDownPos; + bool _draggingNodes; QMap<Node*,QPointF> _oldNodePositions; float _oldWeight; @@ -62,6 +69,7 @@ private: int _oldOutAngle; void getSelection(QSet<Node*> &selNodes, QSet<Edge*> &selEdges); + QSet<Node*> getSelectedNodes(); }; #endif // TIKZSCENE_H diff --git a/src/gui/toolpalette.cpp b/src/gui/toolpalette.cpp index 0a832a6..0d0bd30 100644 --- a/src/gui/toolpalette.cpp +++ b/src/gui/toolpalette.cpp @@ -48,3 +48,21 @@ ToolPalette::Tool ToolPalette::currentTool() const else return SELECT; } +void ToolPalette::setCurrentTool(ToolPalette::Tool tool) +{ + switch(tool) { + case SELECT: + select->setChecked(true); + break; + case VERTEX: + vertex->setChecked(true); + break; + case EDGE: + edge->setChecked(true); + break; + case CROP: + crop->setChecked(true); + break; + } +} + diff --git a/src/gui/toolpalette.h b/src/gui/toolpalette.h index c28b5a1..1876043 100644 --- a/src/gui/toolpalette.h +++ b/src/gui/toolpalette.h @@ -23,6 +23,7 @@ public: }; Tool currentTool() const; + void setCurrentTool(Tool tool); private: QActionGroup *tools; QAction *select; diff --git a/src/gui/undocommands.cpp b/src/gui/undocommands.cpp index 9c6a9c3..0ebfd21 100644 --- a/src/gui/undocommands.cpp +++ b/src/gui/undocommands.cpp @@ -4,12 +4,28 @@ #include <QGraphicsView> +GraphUpdateCommand::GraphUpdateCommand(TikzScene *scene, QUndoCommand *parent) : QUndoCommand(parent), _scene(scene) +{ +} + +void GraphUpdateCommand::undo() +{ + _scene->tikzDocument()->refreshTikz(); + _scene->invalidate(); +} + +void GraphUpdateCommand::redo() +{ + _scene->tikzDocument()->refreshTikz(); + _scene->invalidate(); +} + + MoveCommand::MoveCommand(TikzScene *scene, QMap<Node*, QPointF> oldNodePositions, QMap<Node*, QPointF> newNodePositions, QUndoCommand *parent) : - QUndoCommand(parent), - _scene(scene), + GraphUpdateCommand(scene, parent), _oldNodePositions(oldNodePositions), _newNodePositions(newNodePositions) {} @@ -25,6 +41,7 @@ void MoveCommand::undo() } _scene->refreshAdjacentEdges(_oldNodePositions.keys()); + GraphUpdateCommand::undo(); } void MoveCommand::redo() @@ -37,12 +54,14 @@ void MoveCommand::redo() } _scene->refreshAdjacentEdges(_newNodePositions.keys()); + GraphUpdateCommand::redo(); } EdgeBendCommand::EdgeBendCommand(TikzScene *scene, Edge *edge, float oldWeight, int oldBend, - int oldInAngle, int oldOutAngle) : - _scene(scene), _edge(edge), + int oldInAngle, int oldOutAngle, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), + _edge(edge), _oldWeight(oldWeight), _oldBend(oldBend), _oldInAngle(oldInAngle), _oldOutAngle(oldOutAngle) { @@ -65,6 +84,7 @@ void EdgeBendCommand::undo() break; } } + GraphUpdateCommand::undo(); } void EdgeBendCommand::redo() @@ -80,20 +100,23 @@ void EdgeBendCommand::redo() break; } } + + GraphUpdateCommand::redo(); } DeleteCommand::DeleteCommand(TikzScene *scene, QMap<int, Node *> deleteNodes, QMap<int, Edge *> deleteEdges, - QSet<Edge *> selEdges) : - _scene(scene), _deleteNodes(deleteNodes), - _deleteEdges(deleteEdges), _selEdges(selEdges) + QSet<Edge *> selEdges, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), + _deleteNodes(deleteNodes), _deleteEdges(deleteEdges), _selEdges(selEdges) {} void DeleteCommand::undo() { for (auto it = _deleteNodes.begin(); it != _deleteNodes.end(); ++it) { Node *n = it.value(); + n->attachStyle(); // in case styles have changed _scene->graph()->addNode(n, it.key()); NodeItem *ni = new NodeItem(n); _scene->nodeItems().insert(n, ni); @@ -110,6 +133,8 @@ void DeleteCommand::undo() if (_selEdges.contains(e)) ei->setSelected(true); } + + GraphUpdateCommand::undo(); } void DeleteCommand::redo() @@ -131,10 +156,12 @@ void DeleteCommand::redo() _scene->graph()->removeNode(n); } + + GraphUpdateCommand::redo(); } -AddNodeCommand::AddNodeCommand(TikzScene *scene, Node *node, QRectF newBounds) : - _scene(scene), _node(node), _oldBounds(_scene->sceneRect()), _newBounds(newBounds) +AddNodeCommand::AddNodeCommand(TikzScene *scene, Node *node, QRectF newBounds, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), _node(node), _oldBounds(_scene->sceneRect()), _newBounds(newBounds) { } @@ -148,21 +175,24 @@ void AddNodeCommand::undo() _scene->graph()->removeNode(_node); _scene->setBounds(_oldBounds); + + GraphUpdateCommand::undo(); } void AddNodeCommand::redo() { - // TODO: get the current style + _node->attachStyle(); // in case styles have changed _scene->graph()->addNode(_node); NodeItem *ni = new NodeItem(_node); _scene->nodeItems().insert(_node, ni); _scene->addItem(ni); _scene->setBounds(_newBounds); + GraphUpdateCommand::redo(); } -AddEdgeCommand::AddEdgeCommand(TikzScene *scene, Edge *edge) : - _scene(scene), _edge(edge) +AddEdgeCommand::AddEdgeCommand(TikzScene *scene, Edge *edge, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), _edge(edge) { } @@ -174,6 +204,7 @@ void AddEdgeCommand::undo() delete ei; _scene->graph()->removeEdge(_edge); + GraphUpdateCommand::undo(); } void AddEdgeCommand::redo() @@ -188,10 +219,12 @@ void AddEdgeCommand::redo() if (!_scene->graph()->nodes().isEmpty()) { ei->stackBefore(_scene->nodeItems()[_scene->graph()->nodes().first()]); } + + GraphUpdateCommand::redo(); } -ChangeEdgeModeCommand::ChangeEdgeModeCommand(TikzScene *scene, Edge *edge) : - _scene(scene), _edge(edge) +ChangeEdgeModeCommand::ChangeEdgeModeCommand(TikzScene *scene, Edge *edge, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), _edge(edge) { } @@ -199,10 +232,96 @@ void ChangeEdgeModeCommand::undo() { _edge->setBasicBendMode(!_edge->basicBendMode()); _scene->edgeItems()[_edge]->readPos(); + GraphUpdateCommand::undo(); } void ChangeEdgeModeCommand::redo() { _edge->setBasicBendMode(!_edge->basicBendMode()); _scene->edgeItems()[_edge]->readPos(); + GraphUpdateCommand::redo(); +} + +ApplyStyleToNodesCommand::ApplyStyleToNodesCommand(TikzScene *scene, QString style, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), _style(style), _oldStyles() +{ + foreach (QGraphicsItem *it, scene->selectedItems()) { + if (NodeItem *ni = dynamic_cast<NodeItem*>(it)) { + _oldStyles.insert(ni->node(), ni->node()->styleName()); + } + } +} + +void ApplyStyleToNodesCommand::undo() +{ + foreach (Node *n, _oldStyles.keys()) { + n->setStyleName(_oldStyles[n]); + n->attachStyle(); + } + + GraphUpdateCommand::undo(); +} + +void ApplyStyleToNodesCommand::redo() +{ + foreach (Node *n, _oldStyles.keys()) { + n->setStyleName(_style); + n->attachStyle(); + } + GraphUpdateCommand::redo(); +} + +PasteCommand::PasteCommand(TikzScene *scene, Graph *graph, QUndoCommand *parent) : + GraphUpdateCommand(scene, parent), _graph(graph) +{ + _oldSelection = scene->selectedItems(); +} + +void PasteCommand::undo() +{ + _scene->clearSelection(); + + foreach (Edge *e, _graph->edges()) { + EdgeItem *ei = _scene->edgeItems()[e]; + _scene->edgeItems().remove(e); + _scene->removeItem(ei); + delete ei; + + _scene->graph()->removeEdge(e); + } + + foreach (Node *n, _graph->nodes()) { + NodeItem *ni = _scene->nodeItems()[n]; + _scene->nodeItems().remove(n); + _scene->removeItem(ni); + delete ni; + + _scene->graph()->removeNode(n); + } + + foreach (auto it, _oldSelection) it->setSelected(true); + + GraphUpdateCommand::undo(); +} + +void PasteCommand::redo() +{ + _scene->clearSelection(); + _scene->graph()->insertGraph(_graph); + + foreach (Node *n, _graph->nodes()) { + n->attachStyle(); // in case styles have changed + NodeItem *ni = new NodeItem(n); + _scene->nodeItems().insert(n, ni); + _scene->addItem(ni); + ni->setSelected(true); + } + + foreach (Edge *e, _graph->edges()) { + EdgeItem *ei = new EdgeItem(e); + _scene->edgeItems().insert(e, ei); + _scene->addItem(ei); + } + + GraphUpdateCommand::redo(); } diff --git a/src/gui/undocommands.h b/src/gui/undocommands.h index eea39ae..354e455 100644 --- a/src/gui/undocommands.h +++ b/src/gui/undocommands.h @@ -14,7 +14,17 @@ #include <QUndoCommand> -class MoveCommand : public QUndoCommand +class GraphUpdateCommand : public QUndoCommand { +public: + explicit GraphUpdateCommand(TikzScene *scene, + QUndoCommand *parent = 0); + void undo() override; + void redo() override; +protected: + TikzScene *_scene; +}; + +class MoveCommand : public GraphUpdateCommand { public: explicit MoveCommand(TikzScene *scene, @@ -24,21 +34,20 @@ public: void undo() override; void redo() override; private: - TikzScene *_scene; QMap<Node*,QPointF> _oldNodePositions; QMap<Node*,QPointF> _newNodePositions; }; -class EdgeBendCommand : public QUndoCommand +class EdgeBendCommand : public GraphUpdateCommand { public: explicit EdgeBendCommand(TikzScene *scene, Edge *edge, float oldWeight, int oldBend, - int oldInAngle, int oldOutAngle); + int oldInAngle, int oldOutAngle, + QUndoCommand *parent = 0); void undo() override; void redo() override; private: - TikzScene *_scene; Edge *_edge; float _oldWeight; int _oldBend; @@ -50,55 +59,75 @@ private: int _newOutAngle; }; -class DeleteCommand : public QUndoCommand +class DeleteCommand : public GraphUpdateCommand { public: explicit DeleteCommand(TikzScene *scene, QMap<int,Node*> deleteNodes, QMap<int,Edge*> deleteEdges, - QSet<Edge*> selEdges); + QSet<Edge*> selEdges, + QUndoCommand *parent = 0); void undo() override; void redo() override; private: - TikzScene *_scene; QMap<int,Node*> _deleteNodes; QMap<int,Edge*> _deleteEdges; QSet<Edge*> _selEdges; }; -class AddNodeCommand : public QUndoCommand +class AddNodeCommand : public GraphUpdateCommand { public: - explicit AddNodeCommand(TikzScene *scene, Node *node, QRectF newBounds); + explicit AddNodeCommand(TikzScene *scene, Node *node, QRectF newBounds, + QUndoCommand *parent = 0); void undo() override; void redo() override; private: - TikzScene *_scene; Node *_node; QRectF _oldBounds; QRectF _newBounds; }; -class AddEdgeCommand : public QUndoCommand +class AddEdgeCommand : public GraphUpdateCommand { public: - explicit AddEdgeCommand(TikzScene *scene, Edge *edge); + explicit AddEdgeCommand(TikzScene *scene, Edge *edge, QUndoCommand *parent = 0); void undo() override; void redo() override; private: - TikzScene *_scene; Edge *_edge; }; -class ChangeEdgeModeCommand : public QUndoCommand +class ChangeEdgeModeCommand : public GraphUpdateCommand { public: - explicit ChangeEdgeModeCommand(TikzScene *scene, Edge *edge); + explicit ChangeEdgeModeCommand(TikzScene *scene, Edge *edge, QUndoCommand *parent = 0); void undo() override; void redo() override; private: - TikzScene *_scene; Edge *_edge; }; +class ApplyStyleToNodesCommand : public GraphUpdateCommand +{ +public: + explicit ApplyStyleToNodesCommand(TikzScene *scene, QString style, QUndoCommand *parent = 0); + void undo() override; + void redo() override; +private: + QString _style; + QMap<Node*,QString> _oldStyles; +}; + +class PasteCommand : public GraphUpdateCommand +{ +public: + explicit PasteCommand(TikzScene *scene, Graph *graph, QUndoCommand *parent = 0); + void undo() override; + void redo() override; +private: + Graph *_graph; + QList<QGraphicsItem*> _oldSelection; +}; + #endif // UNDOCOMMANDS_H |