From 4504af7468ec886ac02a13c23524a73595b0d543 Mon Sep 17 00:00:00 2001 From: Denes Matetelki Date: Mon, 4 Jul 2011 20:13:23 +0200 Subject: [PATCH] removenode became undo command --- include/commands.h | 30 ++++++++++++ include/graphlogic.h | 3 ++ include/node.h | 5 +- src/commands.cpp | 108 +++++++++++++++++++++++++++++++++++++++++-- src/graphlogic.cpp | 39 ++-------------- src/node.cpp | 41 +++++++++++----- 6 files changed, 177 insertions(+), 49 deletions(-) diff --git a/include/commands.h b/include/commands.h index 8bf1686..705011e 100644 --- a/include/commands.h +++ b/include/commands.h @@ -21,6 +21,13 @@ public: const char* what() const throw(); }; +class CannotDeleteBaseNodeException : public std::exception +{ +public: + const char* what() const throw(); +}; + + class InsertNodeCommand : public QUndoCommand { @@ -35,9 +42,32 @@ public: private: GraphLogic *m_graphLogic; + Node *m_node; QPointF m_pos; Node *m_activeNode; + Edge *m_edge; +}; + +class RemoveNodeCommand : public QUndoCommand +{ + +public: + + RemoveNodeCommand(GraphLogic *graphLogic); + + void undo(); + void redo(); + +private: + + GraphLogic *m_graphLogic; + + Node *m_activeNode; + Node *m_hintNode; + + QList m_nodeList; + QList m_edgeList; }; #endif // COMMANDS_H diff --git a/include/graphlogic.h b/include/graphlogic.h index 9646fd8..541847c 100644 --- a/include/graphlogic.h +++ b/include/graphlogic.h @@ -10,7 +10,9 @@ class GraphWidget; + class InsertNodeCommand; +class RemoveNodeCommand; class GraphLogic : public QObject { @@ -101,6 +103,7 @@ private: friend class InsertNodeCommand; + friend class RemoveNodeCommand; }; #endif // GRAPHLOGIC_H diff --git a/include/node.h b/include/node.h index 356d246..100b589 100644 --- a/include/node.h +++ b/include/node.h @@ -22,10 +22,13 @@ public: // add/remove edges void addEdge(Edge *edge, bool startsFromThisNode); void deleteEdge(Node *otherEnd); - void removeEdgeFromList(Edge *edge); + void deleteEdges(); + void removeEdge(Edge *edge); void removeEdges(); + // graph traversal + QList edges() const; QList edgesFrom(const bool &excludeSecondaries = true) const; QList edgesToThis(const bool &excludeSecondaries = true) const; Edge * edgeTo(const Node* node) const; diff --git a/src/commands.cpp b/src/commands.cpp index e268e93..99259c6 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -1,6 +1,7 @@ #include "include/commands.h" #include +#include #include @@ -17,16 +18,22 @@ const char* CannotPlaceNewNodeException::what() const throw() toStdString().c_str(); } +const char* CannotDeleteBaseNodeException::what() const throw() +{ + return QObject::tr("Base node cannot be deleted.").toStdString().c_str(); +} + InsertNodeCommand::InsertNodeCommand(GraphLogic *graphLogic) : m_graphLogic(graphLogic) , m_node(0) , m_activeNode(m_graphLogic->m_activeNode) + , m_edge(0) { if (!m_activeNode) throw NoActiveNodeException(); - setText(QObject::tr("New node added to ").append( + setText(QObject::tr("Node added to ").append( m_activeNode == m_graphLogic->m_nodeList.first() ? QObject::tr("Base node") : QString("\"").append(m_activeNode->toPlainText().append("\"")))); @@ -55,6 +62,11 @@ InsertNodeCommand::InsertNodeCommand(GraphLogic *graphLogic) m_node->setColor(m_activeNode->color()); m_node->setTextColor(m_activeNode->textColor()); m_node->setHtml(QString("")); + + m_edge = new Edge(m_activeNode, m_node); + m_edge->setColor(m_node->color()); + m_edge->setWidth(m_node->scale()*2 + 1); + m_edge->setSecondary(false); } void InsertNodeCommand::undo() @@ -62,7 +74,10 @@ void InsertNodeCommand::undo() m_graphLogic->m_nodeList.removeAll(m_node); m_graphLogic->m_graphWidget->scene()->removeItem(m_node); - m_node->removeEdges(); +// m_node->deleteEdges(); + m_edge->sourceNode()->removeEdge(m_edge); + m_edge->destNode()->removeEdge(m_edge); + m_graphLogic->m_graphWidget->scene()->removeItem(m_edge); m_graphLogic->setActiveNode(m_activeNode); @@ -76,7 +91,10 @@ void InsertNodeCommand::redo() m_node->setPos(m_pos); - m_graphLogic->addEdge(m_activeNode, m_node); +// m_graphLogic->addEdge(m_activeNode, m_node); + m_edge->sourceNode()->addEdge(m_edge,true); + m_edge->destNode()->addEdge(m_edge,false); + m_graphLogic->m_graphWidget->scene()->addItem(m_edge); m_graphLogic->setActiveNode(m_node); @@ -89,3 +107,87 @@ void InsertNodeCommand::redo() if (m_graphLogic->m_showingNodeNumbers) m_graphLogic->showNodeNumbers(); } + +RemoveNodeCommand::RemoveNodeCommand(GraphLogic *graphLogic) + : m_graphLogic(graphLogic) + , m_activeNode(m_graphLogic->m_activeNode) + , m_hintNode(m_graphLogic->m_hintNode) +{ + if (!m_activeNode) + throw NoActiveNodeException(); + + if (m_activeNode == m_graphLogic->m_nodeList.first()) + throw CannotDeleteBaseNodeException(); + + setText(QObject::tr("Node removed \"").append( + m_activeNode->toPlainText().append("\""))); + + // remove just the active Node or it's subtree too? + if (QApplication::keyboardModifiers() & Qt::ControlModifier && + QApplication::keyboardModifiers() & Qt::ShiftModifier) + { + m_nodeList = m_activeNode->subtree(); + setText(text().append(QObject::tr(" with subtree"))); + } + else + { + m_nodeList.push_back(m_activeNode); + } + + foreach(Node *node, m_nodeList) + foreach(Edge *edge, node->edges()) + if (m_edgeList.indexOf(edge) == -1) + m_edgeList.push_back(edge); +} + +void RemoveNodeCommand::undo() +{ + foreach (Node *node, m_nodeList) + { + m_graphLogic->m_graphWidget->scene()->addItem(node); + m_graphLogic->m_nodeList.append(node); + } + + foreach (Edge *edge, m_edgeList) + { + edge->sourceNode()->addEdge(edge,true); + edge->destNode()->addEdge(edge,false); + m_graphLogic->m_graphWidget->scene()->addItem(edge); + } + + emit m_graphLogic->contentChanged(false); + m_graphLogic->m_activeNode = m_activeNode; + m_graphLogic->m_hintNode = m_hintNode; + + + // it we are in hint mode, the numbers shall be re-calculated + if (m_graphLogic->m_showingNodeNumbers) + m_graphLogic->showNodeNumbers(); +} + +void RemoveNodeCommand::redo() +{ + foreach(Node *node, m_nodeList) + { + if (m_graphLogic->m_hintNode==node) + m_graphLogic->m_hintNode=0; + + m_graphLogic->m_nodeList.removeAll(node); + m_graphLogic->m_graphWidget->scene()->removeItem(node); + } + + foreach(Edge *edge, m_edgeList) + { + edge->sourceNode()->removeEdge(edge); + edge->destNode()->removeEdge(edge); + m_graphLogic->m_graphWidget->scene()->removeItem(edge); + } + + m_graphLogic->m_activeNode = 0; + + emit m_graphLogic->contentChanged(); + + // it we are in hint mode, the numbers shall be re-calculated + if (m_graphLogic->m_showingNodeNumbers) + m_graphLogic->showNodeNumbers(); +} diff --git a/src/graphlogic.cpp b/src/graphlogic.cpp index f14342b..985a1b3 100644 --- a/src/graphlogic.cpp +++ b/src/graphlogic.cpp @@ -308,45 +308,16 @@ void GraphLogic::insertNode() void GraphLogic::removeNode() { - if (!m_activeNode) + try { - emit notification(tr("No active node.")); - return; + QUndoCommand *removeNodeCommand = new RemoveNodeCommand(this); + m_undoStack->push(removeNodeCommand); } - - if (m_activeNode == m_nodeList.first()) + catch (std::exception &e) { - emit notification(tr("Base node cannot be deleted.")); + emit notification(e.what()); return; } - - // remove just the active Node or it's subtree too? - QList nodeList; - if (QApplication::keyboardModifiers() & Qt::ControlModifier && - QApplication::keyboardModifiers() & Qt::ShiftModifier) - { - nodeList = m_activeNode->subtree(); - } - else - { - nodeList.push_back(m_activeNode); - } - - foreach(Node *node, nodeList) - { - if (m_hintNode==node) - m_hintNode=0; - - m_nodeList.removeAll(node); - delete node; - } - - m_activeNode = 0; - emit contentChanged(); - - // it we are in hint mode, the numbers shall be re-calculated - if (m_showingNodeNumbers) - showNodeNumbers(); } void GraphLogic::nodeEdited() diff --git a/src/node.cpp b/src/node.cpp index 50e5a4c..404e0e1 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -35,7 +35,7 @@ Node::Node() Node::~Node() { - removeEdges(); + deleteEdges(); } void Node::addEdge(Edge *edge, bool startsFromThisNode) @@ -55,15 +55,28 @@ void Node::deleteEdge(Node *otherEnd) it->edge->destNode() == otherEnd)) { Edge *tmp = it->edge; - tmp->sourceNode()->removeEdgeFromList(tmp); - tmp->destNode()->removeEdgeFromList(tmp); + tmp->sourceNode()->removeEdge(tmp); + tmp->destNode()->removeEdge(tmp); delete tmp; return; } } } -void Node::removeEdgeFromList(Edge *edge) +void Node::deleteEdges() +{ + foreach (EdgeElement element, m_edgeList) + { + Edge *tmp = element.edge; + tmp->sourceNode()->removeEdge(tmp); + tmp->destNode()->removeEdge(tmp); + + /// @bug crashes sometimes + delete tmp; + } +} + +void Node::removeEdge(Edge *edge) { for(QList::iterator it = m_edgeList.begin(); it != m_edgeList.end(); it++) @@ -78,17 +91,23 @@ void Node::removeEdgeFromList(Edge *edge) void Node::removeEdges() { - foreach (EdgeElement element, m_edgeList) + for(QList::iterator it = m_edgeList.begin(); + it != m_edgeList.end(); it++) { - Edge *tmp = element.edge; - tmp->sourceNode()->removeEdgeFromList(tmp); - tmp->destNode()->removeEdgeFromList(tmp); - - /// @bug crashes sometimes - delete tmp; + m_edgeList.erase(it); } } +QList Node::edges() const +{ + QList list; + + foreach(EdgeElement element, m_edgeList) + list.push_back(element.edge); + + return list; +} + // edges from this Node. Exclude secondaries if needed (calc subtree) QList Node::edgesFrom(const bool &excludeSecondaries) const {