add/remove edge are undo commands

master
Denes Matetelki 14 years ago
parent 4504af7468
commit 77960e146a

@ -9,6 +9,8 @@
class GraphLogic;
// exceptions:
class NoActiveNodeException : public std::exception
{
public:
@ -27,7 +29,20 @@ public:
const char* what() const throw();
};
class BaseNodeCannotBeEdgeTargetException : public std::exception
{
public:
const char* what() const throw();
};
class EdgeExistsBetweenNodesException : public std::exception
{
public:
const char* what() const throw();
};
// commands:
class InsertNodeCommand : public QUndoCommand
{
@ -70,4 +85,44 @@ private:
QList <Edge *> m_edgeList;
};
class AddEdgeCommand : public QUndoCommand
{
public:
AddEdgeCommand(GraphLogic *graphLogic, Node *source, Node *destinaion);
void undo();
void redo();
private:
GraphLogic *m_graphLogic;
Node *m_activeNode;
Node *m_source;
Node *m_destination;
Edge *m_edge;
};
class RemoveEdgeCommand : public QUndoCommand
{
public:
RemoveEdgeCommand(GraphLogic *graphLogic, Node *source, Node *destinaion);
void undo();
void redo();
private:
GraphLogic *m_graphLogic;
Node *m_activeNode;
Node *m_source;
Node *m_destination;
Edge *m_edge;
};
#endif // COMMANDS_H

@ -13,6 +13,8 @@ class GraphWidget;
class InsertNodeCommand;
class RemoveNodeCommand;
class AddEdgeCommand;
class RemoveEdgeCommand;
class GraphLogic : public QObject
{
@ -34,15 +36,15 @@ public:
public slots:
// commands from toolbars:
void insertNode();
void removeNode(); /// @todo Rewrite as an undo action
void insertNode(); // undo command
void removeNode(); // undo command
void nodeEdited(); /// @todo Rewrite as an undo action
void scaleUp(); /// @todo Rewrite as an undo action
void scaleDown(); /// @todo Rewrite as an undo action
void nodeColor();
void nodeTextColor();
void addEdge(); /// @todo Rewrite as an undo action
void removeEdge(); /// @todo Rewrite as an undo action
void addEdge();
void removeEdge();
void hintMode();
void insertPicture(const QString &picture); /// @todo Rewrite as an undo action
@ -78,8 +80,8 @@ private:
// functions on the edges
QList<Edge *> allEdges() const;
void addEdge(Node *source, Node *destination);
void removeEdge(Node* source, Node *destination);
void addEdge(Node *source, Node *destination); // undo command
void removeEdge(Node* source, Node *destination); // undo command
// hint mode's nodenumber handling functions
void showNodeNumbers();
@ -104,6 +106,8 @@ private:
friend class InsertNodeCommand;
friend class RemoveNodeCommand;
friend class AddEdgeCommand;
friend class RemoveEdgeCommand;
};
#endif // GRAPHLOGIC_H

@ -23,6 +23,17 @@ const char* CannotDeleteBaseNodeException::what() const throw()
return QObject::tr("Base node cannot be deleted.").toStdString().c_str();
}
const char* BaseNodeCannotBeEdgeTargetException::what() const throw()
{
return QObject::tr("Base node cannot be a target.").toStdString().c_str();
}
const char* EdgeExistsBetweenNodesException::what() const throw()
{
return QObject::tr("There is already an edge between these two nodes.").
toStdString().c_str();
}
InsertNodeCommand::InsertNodeCommand(GraphLogic *graphLogic)
: m_graphLogic(graphLogic)
@ -191,3 +202,100 @@ void RemoveNodeCommand::redo()
if (m_graphLogic->m_showingNodeNumbers)
m_graphLogic->showNodeNumbers();
}
AddEdgeCommand::AddEdgeCommand(GraphLogic *graphLogic, Node *source, Node *destinaion)
: m_graphLogic(graphLogic)
, m_activeNode(m_graphLogic->m_activeNode)
, m_source(source)
, m_destination(destinaion)
{
if (!m_activeNode)
throw NoActiveNodeException();
if (m_destination == m_graphLogic->m_nodeList.first())
throw BaseNodeCannotBeEdgeTargetException();
if (m_source->isConnected(m_destination))
throw EdgeExistsBetweenNodesException();
setText(QObject::tr("Edge added between \"").append(
m_source->toPlainText()).append(
QObject::tr("\" and \"").append(
m_destination->toPlainText()).append("\"")));
// aviod the graph beeing acyclic. (ok, Nodes having multiple parents)
bool sec(false);
if (!m_destination->edgesToThis().empty())
{
emit m_graphLogic->notification(
QObject::tr("The graph is acyclic, edge added as secondary edge."));
sec = true;
}
m_edge = new Edge(m_source, m_destination);
m_edge->setColor(m_destination->color());
m_edge->setWidth(m_destination->scale()*2 + 1);
// The Edge is secondary, because the Node already has a parent
// (it is already a destination of another Edge)
m_edge->setSecondary(sec);
}
void AddEdgeCommand::undo()
{
m_source->removeEdge(m_edge);
m_destination->removeEdge(m_edge);
m_graphLogic->m_graphWidget->scene()->removeItem(m_edge);
m_graphLogic->setActiveNode(m_activeNode);
emit m_graphLogic->contentChanged(false);
}
void AddEdgeCommand::redo()
{
m_source->addEdge(m_edge, true);
m_destination->addEdge(m_edge, false);
m_graphLogic->m_graphWidget->scene()->addItem(m_edge);
m_graphLogic->setActiveNode(m_destination);
emit m_graphLogic->contentChanged();
}
RemoveEdgeCommand::RemoveEdgeCommand(GraphLogic *graphLogic, Node *source, Node *destinaion)
: m_graphLogic(graphLogic)
, m_activeNode(m_graphLogic->m_activeNode)
, m_source(source)
, m_destination(destinaion)
, m_edge(source->edgeTo(destinaion))
{
setText(QObject::tr("Edge releted between \"").append(
m_source->toPlainText()).append(
QObject::tr("\" and \"").append(
m_destination->toPlainText()).append("\"")));
}
void RemoveEdgeCommand::undo()
{
m_source->addEdge(m_edge, true);
m_destination->addEdge(m_edge, false);
m_graphLogic->m_graphWidget->scene()->addItem(m_edge);
m_graphLogic->setActiveNode(m_destination);
emit m_graphLogic->contentChanged(false);
}
void RemoveEdgeCommand::redo()
{
m_source->removeEdge(m_edge);
m_destination->removeEdge(m_edge);
m_graphLogic->m_graphWidget->scene()->removeItem(m_edge);
m_graphLogic->setActiveNode(m_activeNode);
emit m_graphLogic->contentChanged();
}

@ -699,51 +699,16 @@ QList<Edge *> GraphLogic::allEdges() const
void GraphLogic::addEdge(Node *source, Node *destination)
{
if (!m_activeNode)
try
{
emit notification(tr("No active node."));
return;
QUndoCommand *addEdgeCommand = new AddEdgeCommand(this, source, destination);
m_undoStack->push(addEdgeCommand);
}
if (destination == m_nodeList.first())
catch (std::exception &e)
{
setActiveNode(destination);
emit notification(
tr("Root element cannot be an edge target."));
emit notification(e.what());
return;
}
if (source->isConnected(destination))
{
setActiveNode(destination);
emit notification(
tr("There is already an edge between these two nodes."));
}
else
{
// aviod the graph beeing acyclic. (ok, Nodes having multiple parents)
bool sec(false);
if (!destination->edgesToThis().empty())
{
emit notification(
tr("The graph is acyclic, edge added as secondary edge."));
sec = true;
}
Edge *edge = new Edge(source, destination);
source->addEdge(edge, true);
destination->addEdge(edge, false);
edge->setColor(destination->color());
edge->setWidth(destination->scale()*2 + 1);
// The Edge is secondary, because the Node already has a parent
// (it is already a destination of another Edge)
edge->setSecondary(sec);
m_graphWidget->scene()->addItem(edge);
setActiveNode(destination);
emit contentChanged();
}
}
void GraphLogic::removeEdge(Node *source, Node *destination)

Loading…
Cancel
Save