Adding/removing nodes, adding edges.

for/release
dmatetelki 11 years ago
parent 7f068f8ffd
commit fa15a7c30a

@ -72,6 +72,7 @@ public:
// Lookup // Lookup
bool contains(const_reference data) const { return m_vertices.find(data) != m_vertices.end(); } bool contains(const_reference data) const { return m_vertices.find(data) != m_vertices.end(); }
std::vector<value_type> vertices() const; std::vector<value_type> vertices() const;
bool connected(const_reference source, const_reference destination) const;
std::vector<value_type> neighboursOf(const_reference data) const; std::vector<value_type> neighboursOf(const_reference data) const;
std::vector<Edge> edges() const; std::vector<Edge> edges() const;
@ -251,6 +252,13 @@ inline std::vector<typename Graph<V>::value_type> Graph<V>::vertices() const
return retval; return retval;
} }
template <typename V>
inline bool Graph<V>::connected(const_reference source, const_reference destination) const
{
std::vector<V> neightbours = neighboursOf(source);
return std::find(neightbours.begin(), neightbours.end(), destination) != neightbours.end();
}
template <typename V> template <typename V>
inline std::vector<V> Graph<V>::neighboursOf(const_reference data) const inline std::vector<V> Graph<V>::neighboursOf(const_reference data) const
{ {
@ -281,7 +289,9 @@ inline std::vector<typename Graph<V>::Edge> Graph<V>::edges() const
template <typename V> template <typename V>
inline void Graph<V>::eraseEdge(edge_container& v, const_reference data) { inline void Graph<V>::eraseEdge(edge_container& v, const_reference data) {
v.erase(std::remove(v.begin(), v.end()), v.end()); v.erase(std::remove_if(v.begin(), v.end(),
[&data](const_reference d) { return d == data; }),
v.end());
} }

@ -12,6 +12,8 @@
#include <QtGui/QApplication> #include <QtGui/QApplication>
#include <QtCore/QDebug>
namespace std { namespace std {
template <> template <>
struct hash<float2> struct hash<float2>
@ -25,17 +27,26 @@ namespace std {
}; };
} }
namespace {
// for the map // for the map
bool operator< (const float2& v1, const float2& v2) // bool operator< (const float2& v1, const float2& v2)
{ // {
return length(v1) < length(v2); // return length(v1) < length(v2);
} // }
float2 inline float2FromQPointF(const QPointF& p) float2 inline float2FromQPointF(const QPointF& p)
{ {
return float2(p.x(), p.y()); return float2(p.x(), p.y());
} }
QPointF inline QPointFFromfloat2(const float2& f)
{
return QPointF(f.x, f.y);
}
} // anonym namespace
GraphWidget::GraphWidget(Graph<float2>* graph, QWidget *p) GraphWidget::GraphWidget(Graph<float2>* graph, QWidget *p)
: QGraphicsView(p) : QGraphicsView(p)
@ -59,24 +70,23 @@ void GraphWidget::itemMoved(const QPointF oldPos, const QPointF newPos)
{ {
float2 old_v = float2FromQPointF(oldPos); float2 old_v = float2FromQPointF(oldPos);
float2 new_v = float2FromQPointF(newPos); float2 new_v = float2FromQPointF(newPos);
// if old_pos not found, returns silently
m_graph->modifyVertex(old_v, new_v); m_graph->modifyVertex(old_v, new_v);
} }
void GraphWidget::updateFromGraph() void GraphWidget::updateFromGraph()
{ {
// scene()->itemAt returns the topmost only which can be an Edge
QMap<float2, Node*> node_map;
for (Graph<float2>::iterator cit = m_graph->begin(); cit != m_graph->end(); ++cit) { for (Graph<float2>::iterator cit = m_graph->begin(); cit != m_graph->end(); ++cit) {
Node *node = new Node(this); Node *node = new Node(this);
scene()->addItem(node); scene()->addItem(node);
node->setPos(cit->x, cit->y); node->setPos(QPointFFromfloat2(*cit));
node_map.insert(*cit, node);
} }
for (Graph<float2>::iterator cit = m_graph->begin(); cit != m_graph->end(); ++cit) { for (Graph<float2>::iterator cit = m_graph->begin(); cit != m_graph->end(); ++cit) {
for (const auto cit2 : m_graph->neighboursOf(*cit)) { for (const auto cit2 : m_graph->neighboursOf(*cit)) {
Node* node1 = node_map.find(*cit).value(); Node* node1 = dynamic_cast<Node*>(scene()->itemAt(QPointFFromfloat2(*cit)));
Node* node2 = node_map.find(cit2).value(); Node* node2 = dynamic_cast<Node*>(scene()->itemAt(QPointFFromfloat2(cit2)));
scene()->addItem(new Edge(node1, node2)); scene()->addItem(new Edge(node1, node2));
} }
} }
@ -91,6 +101,25 @@ void GraphWidget::keyPressEvent(QKeyEvent *e)
case Qt::Key_Minus: case Qt::Key_Minus:
zoomOut(); zoomOut();
break; break;
case Qt::Key_Delete: {
QList <QGraphicsItem* > selectedItems = scene()->selectedItems();
if (selectedItems.isEmpty())
break;
QGraphicsItem* selectedItem = selectedItems.first();
m_graph->removeVertex(float2FromQPointF(selectedItem->pos()));
Node* selectedNode = dynamic_cast<Node*>(selectedItem);
QList<Edge *> edges_of_selected = selectedNode->edges();
for (Edge* edge : edges_of_selected) {
edge->sourceNode()->removeEdge(selectedNode);
edge->destNode()->removeEdge(selectedNode);
scene()->removeItem(edge);
}
scene()->removeItem(selectedItem);
}
case Qt::Key_Insert: { case Qt::Key_Insert: {
QList <QGraphicsItem* > selectedItems = scene()->selectedItems(); QList <QGraphicsItem* > selectedItems = scene()->selectedItems();
if (selectedItems.isEmpty()) if (selectedItems.isEmpty())
@ -103,6 +132,19 @@ void GraphWidget::keyPressEvent(QKeyEvent *e)
const QPoint widget_p = mapFromGlobal(global_p); const QPoint widget_p = mapFromGlobal(global_p);
const QPointF scene_p = mapToScene(widget_p); const QPointF scene_p = mapToScene(widget_p);
/// @bug no hit deteced (hover works) on bottom right corner
QGraphicsItem* item_under_mouse = scene()->itemAt(scene_p);
Node* node_under_mouse = dynamic_cast<Node*>(item_under_mouse);
if (node_under_mouse != 0) { // insert Edge
const float2 source_pos = float2FromQPointF(selectedItem->pos());
const float2 destination_pos = float2FromQPointF(node_under_mouse->pos());
if (m_graph->connected(source_pos, destination_pos))
return;
scene()->addItem(new Edge(selectedNode, node_under_mouse));
m_graph->addEdge(source_pos, destination_pos);
} else { // insert new node
Node *node = new Node(this); Node *node = new Node(this);
scene()->addItem(node); scene()->addItem(node);
node->setPos(scene_p.x(), scene_p.y()); node->setPos(scene_p.x(), scene_p.y());
@ -111,6 +153,10 @@ void GraphWidget::keyPressEvent(QKeyEvent *e)
const float2 source_pos = float2FromQPointF(selectedItem->pos()); const float2 source_pos = float2FromQPointF(selectedItem->pos());
const float2 destination_pos = float2FromQPointF(scene_p); const float2 destination_pos = float2FromQPointF(scene_p);
m_graph->addEdge(source_pos, destination_pos); m_graph->addEdge(source_pos, destination_pos);
selectedItem->setSelected(false);
node->setSelected(true);
}
} }
default: default:
QGraphicsView::keyPressEvent(e); QGraphicsView::keyPressEvent(e);

@ -14,8 +14,9 @@ Node::Node(GraphWidget *graphWidget)
setFlag(ItemIsMovable); setFlag(ItemIsMovable);
setFlag(ItemSendsGeometryChanges); setFlag(ItemSendsGeometryChanges);
setFlag(ItemIsSelectable); setFlag(ItemIsSelectable);
setAcceptHoverEvents(true);
setCacheMode(DeviceCoordinateCache); setCacheMode(DeviceCoordinateCache);
setZValue(-1); setZValue(1); // higher than the edge
} }
void Node::addEdge(Edge *edge) void Node::addEdge(Edge *edge)
@ -24,6 +25,18 @@ void Node::addEdge(Edge *edge)
edge->adjust(); edge->adjust();
} }
void Node::removeEdge(Node* node)
{
// QMutableListIterator<Edge*> i(edgeList);
// while (i.hasNext())
// if (i.next()->sourceNode() == node || i.next()->destNode() == node)
// i.remove();
edgeList.erase(std::remove_if(edgeList.begin(), edgeList.end(),
[node](Edge* e) { return e->sourceNode() == node || e->destNode() == node; }),
edgeList.end());
}
QList<Edge *> Node::edges() const QList<Edge *> Node::edges() const
{ {
return edgeList; return edgeList;
@ -43,24 +56,23 @@ QPainterPath Node::shape() const
return path; return path;
} }
void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem* /*option*/, QWidget *) void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem* option, QWidget *)
{ {
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::darkGray);
painter->drawEllipse(-7, -7, 20, 20);
QRadialGradient gradient(-3, -3, 10); QRadialGradient gradient(-3, -3, 10);
if (isSelected()) { if (isSelected()) {
gradient.setCenter(3, 3); gradient.setCenter(3, 3);
gradient.setFocalPoint(3, 3); gradient.setFocalPoint(3, 3);
gradient.setColorAt(0, Qt::red); gradient.setColorAt(0, Qt::red);
gradient.setColorAt(1, Qt::darkRed); gradient.setColorAt(1, Qt::darkRed);
} else if (option->state & QStyle::State_MouseOver) {
gradient.setColorAt(0, Qt::green);
gradient.setColorAt(1, Qt::darkGreen);
} else { } else {
gradient.setColorAt(0, Qt::yellow); gradient.setColorAt(0, Qt::yellow);
gradient.setColorAt(1, Qt::darkYellow); gradient.setColorAt(1, Qt::darkYellow);
} }
painter->setBrush(gradient);
painter->setBrush(gradient);
painter->setPen(QPen(Qt::black, 0)); painter->setPen(QPen(Qt::black, 0));
painter->drawEllipse(-10, -10, 20, 20); painter->drawEllipse(-10, -10, 20, 20);
} }

@ -14,20 +14,20 @@ public:
Node(GraphWidget *graphWidget); Node(GraphWidget *graphWidget);
void addEdge(Edge *edge); void addEdge(Edge *edge);
void removeEdge(Node* node);
QList<Edge *> edges() const; QList<Edge *> edges() const;
enum { Type = UserType + 1 }; enum { Type = UserType + 1 };
int type() const { return Type; } int type() const override { return Type; }
QRectF boundingRect() const; QRectF boundingRect() const override;
QPainterPath shape() const; QPainterPath shape() const override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
protected: protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value); QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
private: private:
QList<Edge *> edgeList; QList<Edge *> edgeList;

Loading…
Cancel
Save