From 144ed860a6c3a124ce80e3a7c982c614b19a3cdf Mon Sep 17 00:00:00 2001 From: Denes Matetelki Date: Mon, 20 Jun 2011 19:33:38 +0200 Subject: [PATCH] Secondary edges --- edge.cpp | 39 +++++++++++++++++++++++++++---------- edge.h | 7 +++++-- graphwidget.cpp | 25 ++++++++++++++++++++++-- node.cpp | 51 ++++++++++++++++++++++++++++--------------------- node.h | 7 ++++--- 5 files changed, 90 insertions(+), 39 deletions(-) diff --git a/edge.cpp b/edge.cpp index 970c711..663482c 100644 --- a/edge.cpp +++ b/edge.cpp @@ -15,6 +15,7 @@ Edge::Edge(Node *sourceNode, Node *destNode) : m_angle(-1) , m_color(0,0,0) , m_width(1) + , m_secondary(false) { setAcceptedMouseButtons(0); setZValue(1); @@ -62,6 +63,12 @@ void Edge::setWidth(const qreal &width) update(); } +void Edge::setSecondary(const bool &sec) +{ + m_secondary = sec; + update(); +} + void Edge::adjust() { if (!m_sourceNode || !m_destNode) @@ -75,22 +82,25 @@ void Edge::adjust() if (line.length() > qreal(20.)) { // m_sourcePoint = m_sourceNode->intersect(line); -// m_destPoint = m_destNode->intersect(line,true); + m_destPoint = m_destNode->intersect(line,true); + + /// @bug seems not to be updated m_sourcePoint = m_sourceNode->sceneBoundingRect().center(); - m_destPoint = m_destNode->sceneBoundingRect().center(); +// m_destPoint = m_destNode->sceneBoundingRect().center(); } else { m_sourcePoint = m_destPoint = line.p1(); } } +/// @bug not ok yet QRectF Edge::boundingRect() const { if (!m_sourceNode || !m_destNode) return QRectF(); qreal penWidth = 1; - qreal extra = (penWidth + m_arrowSize) / 2.0; + qreal extra = (penWidth + m_arrowSize + m_width) / 2.0; return QRectF(m_sourcePoint, QSizeF(m_destPoint.x() - m_sourcePoint.x(), m_destPoint.y() - m_sourcePoint.y())) @@ -118,7 +128,9 @@ void Edge::paint(QPainter *painter, // Draw the line itself painter->setPen(QPen(m_color, m_width, - Qt::SolidLine, + m_secondary ? + Qt::DashLine : + Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter->drawLine(line); @@ -127,13 +139,20 @@ void Edge::paint(QPainter *painter, return; // Draw the arrow -// QPointF destArrowP1 = m_destPoint + -// QPointF(sin(m_angle - Edge::m_pi / 3) * m_arrowSize, -// cos(m_angle - Edge::m_pi / 3) * m_arrowSize); -// QPointF destArrowP2 = m_destPoint + -// QPointF(sin(m_angle - Edge::m_pi + Edge::m_pi / 3) * m_arrowSize, -// cos(m_angle - Edge::m_pi + Edge::m_pi / 3) * m_arrowSize); + painter->setPen(QPen(m_color, + m_width, + Qt::SolidLine, + Qt::RoundCap, + Qt::RoundJoin)); + + qreal arrowSize = m_arrowSize + m_width; + QPointF destArrowP1 = m_destPoint + + QPointF(sin(m_angle - Edge::m_pi / 3) * arrowSize, + cos(m_angle - Edge::m_pi / 3) * arrowSize); + QPointF destArrowP2 = m_destPoint + + QPointF(sin(m_angle - Edge::m_pi + Edge::m_pi / 3) * arrowSize, + cos(m_angle - Edge::m_pi + Edge::m_pi / 3) * arrowSize); painter->setBrush(m_color); painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 diff --git a/edge.h b/edge.h index 6ca4b25..a29d2ec 100644 --- a/edge.h +++ b/edge.h @@ -16,10 +16,12 @@ public: Node *destNode() const; double getAngle() const; - void setColor(const QColor &color); QColor color() const { return m_color; } - void setWidth(const qreal &width); + void setColor(const QColor &color); qreal width() const { return m_width; } + void setWidth(const qreal &width); + bool secondary() const { return m_secondary; } + void setSecondary(const bool &sec = true ); void adjust(); @@ -40,6 +42,7 @@ private: double m_angle; QColor m_color; qreal m_width; + bool m_secondary; static const qreal m_arrowSize; static const double m_pi; diff --git a/graphwidget.cpp b/graphwidget.cpp index bc99529..81cf562 100644 --- a/graphwidget.cpp +++ b/graphwidget.cpp @@ -95,6 +95,7 @@ void GraphWidget::readContentFromXmlFile(const QString &fileName) e.attribute("text_green").toFloat(), e.attribute("text_blue").toFloat()/*, e.attribute("text_alpha").toFloat()*/)); + m_nodeList.append(node); } } @@ -113,6 +114,7 @@ void GraphWidget::readContentFromXmlFile(const QString &fileName) e.attribute("blue").toFloat()/*, e.attribute("alpha").toFloat()*/)); edge->setWidth(e.attribute("width").toFloat()); + edge->setSecondary(e.attribute("secondary").toInt() ); m_scene->addItem(edge); } @@ -144,7 +146,7 @@ void GraphWidget::writeContentToXmlFile(const QString &fileName) cn.setAttribute( "x", QString::number(node->pos().x())); cn.setAttribute( "y", QString::number(node->pos().y())); cn.setAttribute( "htmlContent", node->toHtml()); - cn.setAttribute( "scale", QString::number(((QGraphicsTextItem*)node)->scale())); + cn.setAttribute( "scale", QString::number(dynamic_cast(node)->scale())); cn.setAttribute( "bg_red", QString::number(node->color().red())); cn.setAttribute( "bg_green", QString::number(node->color().green())); cn.setAttribute( "bg_blue", QString::number(node->color().blue())); @@ -171,6 +173,7 @@ void GraphWidget::writeContentToXmlFile(const QString &fileName) cn.setAttribute( "blue", QString::number(edge->color().blue())); // cn.setAttribute( "alpha", QString::number(edge->color().alpha())); cn.setAttribute( "width", QString::number(edge->width())); + cn.setAttribute( "secondary", QString::number(edge->secondary())); edges_root.appendChild(cn); } @@ -431,7 +434,8 @@ void GraphWidget::keyPressEvent(QKeyEvent *event) { QColor color = dialog.selectedColor(); m_activeNode->setColor(color); - m_activeNode->edgeTo()->setColor(color); + foreach (Edge * edge, m_activeNode->edgesToThis(false)) + edge->setColor(color); } break; @@ -615,6 +619,13 @@ void GraphWidget::nodeSelected(Node *node) void GraphWidget::addEdge(Node *source, Node *destination) { + if (destination == m_nodeList.first()) + { + m_parent->statusBarMsg( + tr("Root element cannot be an edge target.")); + return; + } + if (source->isConnected(destination)) { m_parent->statusBarMsg( @@ -622,8 +633,18 @@ void GraphWidget::addEdge(Node *source, Node *destination) } else { + bool sec(false); + if (!destination->edgesToThis().empty()) + { + m_parent->statusBarMsg( + tr("The graph is acyclic, edge added as secondary edge.")); + sec = true; + } Edge *edge = new Edge(source, destination); edge->setColor(destination->color()); + edge->setWidth(dynamic_cast(destination)->scale()*2 + 1); + edge->setSecondary(sec); + m_scene->addItem(edge); contentChanged(); } diff --git a/node.cpp b/node.cpp index 1d27ae3..fe48356 100644 --- a/node.cpp +++ b/node.cpp @@ -70,10 +70,10 @@ void Node::removeEdgeFromList(Edge *edge) } } -void Node::adjustEdges() -{ - foreach (EdgeElement element, m_edgeList) element.edge->adjust(); -} +//void Node::adjustEdges() +//{ +// foreach (EdgeElement element, m_edgeList) element.edge->adjust(); +//} void Node::setBorder(const bool &hasBorder) { @@ -113,20 +113,21 @@ void Node::setTextColor(const QColor &color) void Node::scale(const qreal &factor) { - if (factor * QGraphicsTextItem::scale() < 0.2 || - factor * QGraphicsTextItem::scale() > 10 ) + if (factor * QGraphicsTextItem::scale() < 0.4 || + factor * QGraphicsTextItem::scale() > 4 ) return; // it would make stuff difficult, like limiting the pos. inside scene -// setTransformOriginPoint(boundingRect().center()); + // setTransformOriginPoint(boundingRect().center()); QGraphicsTextItem::setScale(factor * QGraphicsTextItem::scale()); foreach(EdgeElement element, m_edgeList) if (!element.startsFromThisNode) - element.edge->setWidth(element.edge->width() + - (factor>1 ? 2 : -2) ); - - adjustEdges(); + { + element.edge->setWidth(element.edge->width() * factor ); + /// @bug seems not working + element.edge->adjust(); + } } void Node::showNumber(const int &number, @@ -270,29 +271,35 @@ QPointF Node::intersect(const QLineF &line, const bool &reverse) const return QPointF(0,0); } -QList Node::edgesFrom() const +QList Node::edgesFrom(const bool &excludeSecondaries) const { QList list; foreach(EdgeElement element, m_edgeList) - if (element.startsFromThisNode) + if (element.startsFromThisNode && + (!element.edge->secondary() || !excludeSecondaries)) list.push_back(element.edge); return list; } -Edge * Node::edgeTo(const Node *node) const +QList Node::edgesToThis(const bool &excludeSecondaries) const { - if (!node) - { - foreach(EdgeElement element, m_edgeList) - if (!element.startsFromThisNode) - return element.edge; - } + QList list; foreach(EdgeElement element, m_edgeList) - if (element.edge->sourceNode() == node || - element.edge->destNode() == node) + if (!element.startsFromThisNode && + (!element.edge->secondary() || !excludeSecondaries)) + list.push_back(element.edge); + + return list; +} + +Edge * Node::edgeTo(const Node *node) const +{ + foreach(EdgeElement element, m_edgeList) + if ((element.edge->sourceNode() == node || + element.edge->destNode() == node)) return element.edge; return 0; diff --git a/node.h b/node.h index 0121f0e..6be4552 100644 --- a/node.h +++ b/node.h @@ -19,7 +19,7 @@ public: void addEdge(Edge *edge, bool startsFromThisNode); void deleteEdge(Node *otherEnd); void removeEdgeFromList(Edge *edge); - void adjustEdges(); +// void adjustEdges(); void setBorder(const bool &hasBorder); void setActive(const bool &active = true); @@ -39,8 +39,9 @@ public: bool isConnected(const Node *node) const; QPointF intersect(const QLineF &line, const bool &reverse = false) const; - QList edgesFrom() const; - Edge * edgeTo(const Node* node = 0) const; + QList edgesFrom(const bool &excludeSecondaries = true) const; + QList edgesToThis(const bool &excludeSecondaries = true) const; + Edge * edgeTo(const Node* node) const; protected: