diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:34:13 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:34:13 (GMT) |
commit | 67ad0519fd165acee4a4d2a94fa502e9e4847bd0 (patch) | |
tree | 1dbf50b3dff8d5ca7e9344733968c72704eb15ff /examples/graphicsview/elasticnodes | |
download | Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.zip Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.gz Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.bz2 |
Long live Qt!
Diffstat (limited to 'examples/graphicsview/elasticnodes')
-rw-r--r-- | examples/graphicsview/elasticnodes/edge.cpp | 144 | ||||
-rw-r--r-- | examples/graphicsview/elasticnodes/edge.h | 78 | ||||
-rw-r--r-- | examples/graphicsview/elasticnodes/elasticnodes.pro | 16 | ||||
-rw-r--r-- | examples/graphicsview/elasticnodes/graphwidget.cpp | 224 | ||||
-rw-r--r-- | examples/graphicsview/elasticnodes/graphwidget.h | 71 | ||||
-rw-r--r-- | examples/graphicsview/elasticnodes/main.cpp | 54 | ||||
-rw-r--r-- | examples/graphicsview/elasticnodes/node.cpp | 185 | ||||
-rw-r--r-- | examples/graphicsview/elasticnodes/node.h | 84 |
8 files changed, 856 insertions, 0 deletions
diff --git a/examples/graphicsview/elasticnodes/edge.cpp b/examples/graphicsview/elasticnodes/edge.cpp new file mode 100644 index 0000000..4018c25 --- /dev/null +++ b/examples/graphicsview/elasticnodes/edge.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QPainter> + +#include "edge.h" +#include "node.h" + +#include <math.h> + +static const double Pi = 3.14159265358979323846264338327950288419717; +static double TwoPi = 2.0 * Pi; + +Edge::Edge(Node *sourceNode, Node *destNode) + : arrowSize(10) +{ + setAcceptedMouseButtons(0); + source = sourceNode; + dest = destNode; + source->addEdge(this); + dest->addEdge(this); + adjust(); +} + +Edge::~Edge() +{ +} + +Node *Edge::sourceNode() const +{ + return source; +} + +void Edge::setSourceNode(Node *node) +{ + source = node; + adjust(); +} + +Node *Edge::destNode() const +{ + return dest; +} + +void Edge::setDestNode(Node *node) +{ + dest = node; + adjust(); +} + +void Edge::adjust() +{ + if (!source || !dest) + return; + + QLineF line(mapFromItem(source, 0, 0), mapFromItem(dest, 0, 0)); + qreal length = line.length(); + QPointF edgeOffset((line.dx() * 10) / length, (line.dy() * 10) / length); + + prepareGeometryChange(); + sourcePoint = line.p1() + edgeOffset; + destPoint = line.p2() - edgeOffset; +} + +QRectF Edge::boundingRect() const +{ + if (!source || !dest) + return QRectF(); + + qreal penWidth = 1; + qreal extra = (penWidth + arrowSize) / 2.0; + + return QRectF(sourcePoint, QSizeF(destPoint.x() - sourcePoint.x(), + destPoint.y() - sourcePoint.y())) + .normalized() + .adjusted(-extra, -extra, extra, extra); +} + +void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + if (!source || !dest) + return; + + // Draw the line itself + QLineF line(sourcePoint, destPoint); + painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + painter->drawLine(line); + + // Draw the arrows if there's enough room + double angle = ::acos(line.dx() / line.length()); + if (line.dy() >= 0) + angle = TwoPi - angle; + + QPointF sourceArrowP1 = sourcePoint + QPointF(sin(angle + Pi / 3) * arrowSize, + cos(angle + Pi / 3) * arrowSize); + QPointF sourceArrowP2 = sourcePoint + QPointF(sin(angle + Pi - Pi / 3) * arrowSize, + cos(angle + Pi - Pi / 3) * arrowSize); + QPointF destArrowP1 = destPoint + QPointF(sin(angle - Pi / 3) * arrowSize, + cos(angle - Pi / 3) * arrowSize); + QPointF destArrowP2 = destPoint + QPointF(sin(angle - Pi + Pi / 3) * arrowSize, + cos(angle - Pi + Pi / 3) * arrowSize); + + painter->setBrush(Qt::black); + painter->drawPolygon(QPolygonF() << line.p1() << sourceArrowP1 << sourceArrowP2); + painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2); +} diff --git a/examples/graphicsview/elasticnodes/edge.h b/examples/graphicsview/elasticnodes/edge.h new file mode 100644 index 0000000..9078870 --- /dev/null +++ b/examples/graphicsview/elasticnodes/edge.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EDGE_H +#define EDGE_H + +#include <QGraphicsItem> + +class Node; + +class Edge : public QGraphicsItem +{ +public: + Edge(Node *sourceNode, Node *destNode); + ~Edge(); + + Node *sourceNode() const; + void setSourceNode(Node *node); + + Node *destNode() const; + void setDestNode(Node *node); + + void adjust(); + + enum { Type = UserType + 2 }; + int type() const { return Type; } + +protected: + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + +private: + Node *source, *dest; + + QPointF sourcePoint; + QPointF destPoint; + qreal arrowSize; +}; + +#endif diff --git a/examples/graphicsview/elasticnodes/elasticnodes.pro b/examples/graphicsview/elasticnodes/elasticnodes.pro new file mode 100644 index 0000000..77ca706 --- /dev/null +++ b/examples/graphicsview/elasticnodes/elasticnodes.pro @@ -0,0 +1,16 @@ +HEADERS += \ + edge.h \ + node.h \ + graphwidget.h + +SOURCES += \ + edge.cpp \ + main.cpp \ + node.cpp \ + graphwidget.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/elasticnodes +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS elasticnodes.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/elasticnodes +INSTALLS += target sources diff --git a/examples/graphicsview/elasticnodes/graphwidget.cpp b/examples/graphicsview/elasticnodes/graphwidget.cpp new file mode 100644 index 0000000..5c5029c --- /dev/null +++ b/examples/graphicsview/elasticnodes/graphwidget.cpp @@ -0,0 +1,224 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "graphwidget.h" +#include "edge.h" +#include "node.h" + +#include <QDebug> +#include <QGraphicsScene> +#include <QWheelEvent> + +#include <math.h> + +GraphWidget::GraphWidget() + : timerId(0) +{ + QGraphicsScene *scene = new QGraphicsScene(this); + scene->setItemIndexMethod(QGraphicsScene::NoIndex); + scene->setSceneRect(-200, -200, 400, 400); + setScene(scene); + setCacheMode(CacheBackground); + setViewportUpdateMode(BoundingRectViewportUpdate); + setRenderHint(QPainter::Antialiasing); + setTransformationAnchor(AnchorUnderMouse); + setResizeAnchor(AnchorViewCenter); + + Node *node1 = new Node(this); + Node *node2 = new Node(this); + Node *node3 = new Node(this); + Node *node4 = new Node(this); + centerNode = new Node(this); + Node *node6 = new Node(this); + Node *node7 = new Node(this); + Node *node8 = new Node(this); + Node *node9 = new Node(this); + scene->addItem(node1); + scene->addItem(node2); + scene->addItem(node3); + scene->addItem(node4); + scene->addItem(centerNode); + scene->addItem(node6); + scene->addItem(node7); + scene->addItem(node8); + scene->addItem(node9); + scene->addItem(new Edge(node1, node2)); + scene->addItem(new Edge(node2, node3)); + scene->addItem(new Edge(node2, centerNode)); + scene->addItem(new Edge(node3, node6)); + scene->addItem(new Edge(node4, node1)); + scene->addItem(new Edge(node4, centerNode)); + scene->addItem(new Edge(centerNode, node6)); + scene->addItem(new Edge(centerNode, node8)); + scene->addItem(new Edge(node6, node9)); + scene->addItem(new Edge(node7, node4)); + scene->addItem(new Edge(node8, node7)); + scene->addItem(new Edge(node9, node8)); + + node1->setPos(-50, -50); + node2->setPos(0, -50); + node3->setPos(50, -50); + node4->setPos(-50, 0); + centerNode->setPos(0, 0); + node6->setPos(50, 0); + node7->setPos(-50, 50); + node8->setPos(0, 50); + node9->setPos(50, 50); + + scale(qreal(0.8), qreal(0.8)); + setMinimumSize(400, 400); + setWindowTitle(tr("Elastic Nodes")); +} + +void GraphWidget::itemMoved() +{ + if (!timerId) + timerId = startTimer(1000 / 25); +} + +void GraphWidget::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Up: + centerNode->moveBy(0, -20); + break; + case Qt::Key_Down: + centerNode->moveBy(0, 20); + break; + case Qt::Key_Left: + centerNode->moveBy(-20, 0); + break; + case Qt::Key_Right: + centerNode->moveBy(20, 0); + break; + case Qt::Key_Plus: + scaleView(qreal(1.2)); + break; + case Qt::Key_Minus: + scaleView(1 / qreal(1.2)); + break; + case Qt::Key_Space: + case Qt::Key_Enter: + foreach (QGraphicsItem *item, scene()->items()) { + if (qgraphicsitem_cast<Node *>(item)) + item->setPos(-150 + qrand() % 300, -150 + qrand() % 300); + } + break; + default: + QGraphicsView::keyPressEvent(event); + } +} + +void GraphWidget::timerEvent(QTimerEvent *event) +{ + Q_UNUSED(event); + + QList<Node *> nodes; + foreach (QGraphicsItem *item, scene()->items()) { + if (Node *node = qgraphicsitem_cast<Node *>(item)) + nodes << node; + } + + foreach (Node *node, nodes) + node->calculateForces(); + + bool itemsMoved = false; + foreach (Node *node, nodes) { + if (node->advance()) + itemsMoved = true; + } + + if (!itemsMoved) { + killTimer(timerId); + timerId = 0; + } +} + +void GraphWidget::wheelEvent(QWheelEvent *event) +{ + scaleView(pow((double)2, -event->delta() / 240.0)); +} + +void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect) +{ + Q_UNUSED(rect); + + // Shadow + QRectF sceneRect = this->sceneRect(); + QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height()); + QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5); + if (rightShadow.intersects(rect) || rightShadow.contains(rect)) + painter->fillRect(rightShadow, Qt::darkGray); + if (bottomShadow.intersects(rect) || bottomShadow.contains(rect)) + painter->fillRect(bottomShadow, Qt::darkGray); + + // Fill + QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight()); + gradient.setColorAt(0, Qt::white); + gradient.setColorAt(1, Qt::lightGray); + painter->fillRect(rect.intersect(sceneRect), gradient); + painter->setBrush(Qt::NoBrush); + painter->drawRect(sceneRect); + + // Text + QRectF textRect(sceneRect.left() + 4, sceneRect.top() + 4, + sceneRect.width() - 4, sceneRect.height() - 4); + QString message(tr("Click and drag the nodes around, and zoom with the mouse " + "wheel or the '+' and '-' keys")); + + QFont font = painter->font(); + font.setBold(true); + font.setPointSize(14); + painter->setFont(font); + painter->setPen(Qt::lightGray); + painter->drawText(textRect.translated(2, 2), message); + painter->setPen(Qt::black); + painter->drawText(textRect, message); +} + +void GraphWidget::scaleView(qreal scaleFactor) +{ + qreal factor = matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width(); + if (factor < 0.07 || factor > 100) + return; + + scale(scaleFactor, scaleFactor); +} diff --git a/examples/graphicsview/elasticnodes/graphwidget.h b/examples/graphicsview/elasticnodes/graphwidget.h new file mode 100644 index 0000000..2c86c76 --- /dev/null +++ b/examples/graphicsview/elasticnodes/graphwidget.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GRAPHWIDGET_H +#define GRAPHWIDGET_H + +#include <QtGui/QGraphicsView> + +class Node; + +class GraphWidget : public QGraphicsView +{ + Q_OBJECT + +public: + GraphWidget(); + + void itemMoved(); + +protected: + void keyPressEvent(QKeyEvent *event); + void timerEvent(QTimerEvent *event); + void wheelEvent(QWheelEvent *event); + void drawBackground(QPainter *painter, const QRectF &rect); + + void scaleView(qreal scaleFactor); + +private: + int timerId; + Node *centerNode; +}; + +#endif diff --git a/examples/graphicsview/elasticnodes/main.cpp b/examples/graphicsview/elasticnodes/main.cpp new file mode 100644 index 0000000..8043d58 --- /dev/null +++ b/examples/graphicsview/elasticnodes/main.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> + +#include "graphwidget.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); + + GraphWidget widget; + widget.show(); + return app.exec(); +} diff --git a/examples/graphicsview/elasticnodes/node.cpp b/examples/graphicsview/elasticnodes/node.cpp new file mode 100644 index 0000000..6942fa0 --- /dev/null +++ b/examples/graphicsview/elasticnodes/node.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGraphicsScene> +#include <QGraphicsSceneMouseEvent> +#include <QPainter> +#include <QStyleOption> + +#include "edge.h" +#include "node.h" +#include "graphwidget.h" + +Node::Node(GraphWidget *graphWidget) + : graph(graphWidget) +{ + setFlag(ItemIsMovable); + setCacheMode(DeviceCoordinateCache); + setZValue(1); +} + +void Node::addEdge(Edge *edge) +{ + edgeList << edge; + edge->adjust(); +} + +QList<Edge *> Node::edges() const +{ + return edgeList; +} + +void Node::calculateForces() +{ + if (!scene() || scene()->mouseGrabberItem() == this) { + newPos = pos(); + return; + } + + // Sum up all forces pushing this item away + qreal xvel = 0; + qreal yvel = 0; + foreach (QGraphicsItem *item, scene()->items()) { + Node *node = qgraphicsitem_cast<Node *>(item); + if (!node) + continue; + + QLineF line(mapFromItem(node, 0, 0), QPointF(0, 0)); + qreal dx = line.dx(); + qreal dy = line.dy(); + double l = 2.0 * (dx * dx + dy * dy); + if (l > 0) { + xvel += (dx * 150.0) / l; + yvel += (dy * 150.0) / l; + } + } + + // Now subtract all forces pulling items together + double weight = (edgeList.size() + 1) * 10; + foreach (Edge *edge, edgeList) { + QPointF pos; + if (edge->sourceNode() == this) + pos = mapFromItem(edge->destNode(), 0, 0); + else + pos = mapFromItem(edge->sourceNode(), 0, 0); + xvel += pos.x() / weight; + yvel += pos.y() / weight; + } + + if (qAbs(xvel) < 0.1 && qAbs(yvel) < 0.1) + xvel = yvel = 0; + + QRectF sceneRect = scene()->sceneRect(); + newPos = pos() + QPointF(xvel, yvel); + newPos.setX(qMin(qMax(newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10)); + newPos.setY(qMin(qMax(newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10)); +} + +bool Node::advance() +{ + if (newPos == pos()) + return false; + + setPos(newPos); + return true; +} + +QRectF Node::boundingRect() const +{ + qreal adjust = 2; + return QRectF(-10 - adjust, -10 - adjust, + 23 + adjust, 23 + adjust); +} + +QPainterPath Node::shape() const +{ + QPainterPath path; + path.addEllipse(-10, -10, 20, 20); + return path; +} + +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); + if (option->state & QStyle::State_Sunken) { + gradient.setCenter(3, 3); + gradient.setFocalPoint(3, 3); + gradient.setColorAt(1, QColor(Qt::yellow).light(120)); + gradient.setColorAt(0, QColor(Qt::darkYellow).light(120)); + } else { + gradient.setColorAt(0, Qt::yellow); + gradient.setColorAt(1, Qt::darkYellow); + } + painter->setBrush(gradient); + painter->setPen(QPen(Qt::black, 0)); + painter->drawEllipse(-10, -10, 20, 20); +} + +QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value) +{ + switch (change) { + case ItemPositionHasChanged: + foreach (Edge *edge, edgeList) + edge->adjust(); + graph->itemMoved(); + break; + default: + break; + }; + + return QGraphicsItem::itemChange(change, value); +} + +void Node::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + update(); + QGraphicsItem::mousePressEvent(event); +} + +void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + update(); + QGraphicsItem::mouseReleaseEvent(event); +} diff --git a/examples/graphicsview/elasticnodes/node.h b/examples/graphicsview/elasticnodes/node.h new file mode 100644 index 0000000..42309c4 --- /dev/null +++ b/examples/graphicsview/elasticnodes/node.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NODE_H +#define NODE_H + +#include <QGraphicsItem> +#include <QList> + +class Edge; +class GraphWidget; +QT_BEGIN_NAMESPACE +class QGraphicsSceneMouseEvent; +QT_END_NAMESPACE + +class Node : public QGraphicsItem +{ +public: + Node(GraphWidget *graphWidget); + + void addEdge(Edge *edge); + QList<Edge *> edges() const; + + enum { Type = UserType + 1 }; + int type() const { return Type; } + + void calculateForces(); + bool advance(); + + QRectF boundingRect() const; + QPainterPath shape() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + +protected: + QVariant itemChange(GraphicsItemChange change, const QVariant &value); + + void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + +private: + QList<Edge *> edgeList; + QPointF newPos; + GraphWidget *graph; +}; + +#endif |