The visual links between functions are recovered.
The demo is synchronized with a corresponding demo from Qt (qt486-vc10-32\examples\graphicsview\elasticnodes). It may be successfully compiled by any further versions of Qt including 5.10.1
Also, because Open CASCADE (and OCAF in particular) is improved for usage in multi-threading mode, usage of mutexes is added in this sample (for access to the sharing TNaming_UsedShapes attribute, for example).
@echo off
rem Define QTDIR variable
-set QTDIR=
+set QTDIR=%PRODUCTS_PATH%/qt486-vc10-32
}
}
-
// Returns the results of the function
void BaseDriver::Results(TDF_LabelList& res) const
{
}
}
+// Sets a mutex for execution of the driver.
+void BaseDriver::SetMutex(Standard_Mutex* pmutex)
+{
+ myMutex = pmutex;
+}
+
// Execution.
Standard_Integer BaseDriver::Execute(Handle(TFunction_Logbook)& ) const
{
#if !defined(_BASEDRIVER_H_)
#define _BASEDRIVER_H_
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
#include <Standard_DefineHandle.hxx>
#include <TFunction_Driver.hxx>
#include <TFunction_Logbook.hxx>
#include <TDF_LabelList.hxx>
+#include <Standard_Mutex.hxx>
DEFINE_STANDARD_HANDLE(BaseDriver, TFunction_Driver)
// Returns the results of the function
virtual void Results(TDF_LabelList& res) const;
+ // Sets a mutex for execution of the driver.
+ void SetMutex(Standard_Mutex* pmutex);
+
// Execution.
virtual Standard_Integer Execute(Handle(TFunction_Logbook)& log) const;
DEFINE_STANDARD_RTTIEXT(BaseDriver, TFunction_Driver)
+
+protected:
+ Standard_Mutex* myMutex;
};
#endif // !defined(_BASEDRIVER_H_)
#if !defined(_CIRCLEDRIVER_H_)
#define _CIRCLEDRIVER_H_
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
#include "BaseDriver.h"
#include <Standard_DefineHandle.hxx>
#if !defined(_CONEDRIVER_H_)
#define _CONEDRIVER_H_
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
#include "BaseDriver.h"
#include <Standard_DefineHandle.hxx>
#if !defined(_CYLINDERDRIVER_H_)
#define _CYLINDERDRIVER_H_
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
#include "BaseDriver.h"
#include <Standard_DefineHandle.hxx>
#include "FThread.h"
#include "graphwidget.h"
+#include "BaseDriver.h"
#include <TFunction_Function.hxx>
#include <TFunction_IFunction.hxx>
this->thread_index = theIndex;
}
+void FThread::setMutex(Standard_Mutex* pmutex)
+{
+ this->pmutex = pmutex;
+}
+
// Returns any free (not executed yet) function
TDF_Label FThread::getFreeFunction()
{
const bool must = D->MustExecute(log);
if (must)
{
- // Usage of mutex for execution of Open CASCADE code is the most stupid thing!!!
- // But it makes the execution more reliable...
+ // Usage of mutex for execution of Open CASCADE code.
+ // It makes the execution more reliable...
+ if (!Handle(BaseDriver)::DownCast(D).IsNull())
+ Handle(BaseDriver)::DownCast(D)->SetMutex(pmutex);
+
+ // Execute the driver.
const int ret = D->Execute(log);
if (ret == 0)
{
- // Successfully executed!
+ // Successfuly executed!
itr.SetStatus(L, TFunction_ES_Succeeded);
TDF_LabelList res;
#include <TFunction_Logbook.hxx>
#include <TFunction_Iterator.hxx>
#include <TFunction_Driver.hxx>
+#include <Standard_Mutex.hxx>
class GraphWidget; // shows graphically execution of functions
void setLogbook(const Handle(TFunction_Logbook)& ); // to set logbook with modifications
void setGraph(GraphWidget* ); // to change color of a graph circle
void setThreadIndex(const int ); // to set the index of the thread
+ void setMutex(Standard_Mutex* );
protected:
TFunction_Iterator itr;
Handle(TFunction_Logbook) log;
+ Standard_Mutex* pmutex;
int thread_index;
GraphWidget* graph;
// Make the result
TopoDS_Vertex V = BRepBuilderAPI_MakeVertex(gp_Pnt(x, y, z));
+ if (myMutex)
+ myMutex->Lock();
+
// Set the result
TNaming_Builder B(Label());
B.Generated(V);
+ if (myMutex)
+ myMutex->Unlock();
+
return BaseDriver::Execute(log);
}
\ No newline at end of file
#if !defined(_PointDRIVER_H_)
#define _PointDRIVER_H_
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
#include "BaseDriver.h"
#include <Standard_DefineHandle.hxx>
#if !defined(_PRISMDRIVER_H_)
#define _PRISMDRIVER_H_
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
#include "BaseDriver.h"
#include <Standard_DefineHandle.hxx>
}
}
- //BRepTools::Write(C, "result.brep");
+ if (myMutex)
+ myMutex->Lock();
TNaming_Builder Bui(Label());
Bui.Generated(C);
+ if (myMutex)
+ myMutex->Unlock();
+
return BaseDriver::Execute(log);
}
\ No newline at end of file
#if !defined(_SHAPESAVERDRIVER_H_)
#define _SHAPESAVERDRIVER_H_
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
#include "BaseDriver.h"
#include <Standard_DefineHandle.hxx>
#if !defined(_SIMPLEDRIVER_H_)
#define _SIMPLEDRIVER_H_
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
#include <Standard_DefineHandle.hxx>
#include <TFunction_Driver.hxx>
#include <TFunction_Logbook.hxx>
static const double Pi = 3.14159265358979323846264338327950288419717;
static double TwoPi = 2.0 * Pi;
+//! [0]
Edge::Edge(Node *sourceNode, Node *destNode)
: arrowSize(10)
{
dest->addEdge(this);
adjust();
}
+//! [0]
+//! [1]
Node *Edge::sourceNode() const
{
return source;
{
return dest;
}
+//! [1]
+//! [2]
void Edge::adjust()
{
if (!source || !dest)
sourcePoint = destPoint = line.p1();
}
}
+//! [2]
+//! [3]
QRectF Edge::boundingRect() const
{
if (!source || !dest)
.normalized()
.adjusted(-extra, -extra, extra, extra);
}
+//! [3]
+//! [4]
void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
if (!source || !dest)
QLineF line(sourcePoint, destPoint);
if (qFuzzyCompare(line.length(), qreal(0.)))
return;
+//! [4]
+//! [5]
// Draw the line itself
painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->drawLine(line);
+//! [5]
+//! [6]
// Draw the arrows
double angle = ::acos(line.dx() / line.length());
if (line.dy() >= 0)
painter->drawPolygon(QPolygonF() << line.p1() << sourceArrowP1 << sourceArrowP2);
painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2);
}
+//! [6]
class Node;
+//! [0]
class Edge : public QGraphicsItem
{
public:
Edge(Node *sourceNode, Node *destNode);
Node *sourceNode() const;
-
Node *destNode() const;
void adjust();
QPointF destPoint;
qreal arrowSize;
};
+//! [0]
#endif
#include "node.h"
#include <Standard_WarningsDisable.hxx>
-#include <QDebug>
-#include <QGraphicsScene>
-#include <QWheelEvent>
-#include <QApplication>
+#include <QtGui>
#include <Standard_WarningsRestore.hxx>
#include <math.h>
#include "ShapeSaverDriver.h"
#include "SimpleDriver.h"
-GraphWidget::GraphWidget(QWidget* parent):QGraphicsView(parent),
- myThread1(0),myThread2(0),myThread3(0),myThread4(0)
+//! [0]
+GraphWidget::GraphWidget(QWidget *parent)
+ : QGraphicsView(parent), timerId(0),
+ myThread1(0),myThread2(0),myThread3(0),myThread4(0)
{
QGraphicsScene *scene = new QGraphicsScene(this);
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
- scene->setSceneRect(1, 1, parent->width(), parent->height());
+ scene->setSceneRect(-200, -200, 400, 400);
setScene(scene);
setCacheMode(CacheBackground);
+ setViewportUpdateMode(BoundingRectViewportUpdate);
setRenderHint(QPainter::Antialiasing);
setTransformationAnchor(AnchorUnderMouse);
- setResizeAnchor(AnchorViewCenter);
- scale(0.7, 0.81);
+ scale(qreal(0.8), qreal(0.8));
setMinimumSize(400, 400);
setWindowTitle(tr("Function Mechanism"));
- setNbThreads(1);
+//! [0]
+
+//! [1]
+/*
+ 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);
+*/
+
+ setNbThreads(4);
}
+//! [1]
GraphWidget::~GraphWidget()
{
return false;
// Grid of functions
- int dx = width() / nbx, dy = height() / nby;
- int x0 = dx / 2, y0 = dy / 2; // start position
+ int dx = width() / nbx / 2, dy = height() / nby;
+ int x0 = int(-double(width()) / 1.5) + dx, y0 = int(-double(height()) / 1.5) + dy; // start position
// Draw functions
double x = x0, y = y0;
if (y > height())
y = y0;
fIterator.Next();
+ x = x0 + dx;
}
// Draw dependencies
return !myDocument.IsNull();
}
+//! [2]
+void GraphWidget::itemMoved()
+{
+ if (!timerId)
+ timerId = startTimer(1000 / 25);
+}
+//! [2]
+
+//! [3]
+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:
+ zoomIn();
+ break;
+ case Qt::Key_Minus:
+ zoomOut();
+ break;
+ case Qt::Key_Space:
+ case Qt::Key_Enter:
+ shuffle();
+ break;
+ default:
+ QGraphicsView::keyPressEvent(event);
+ }
+}
+//! [3]
+
+//! [4]
+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;
+ }
+}
+//! [4]
+
+//! [5]
void GraphWidget::wheelEvent(QWheelEvent *event)
{
scaleView(pow((double)2, -event->delta() / 240.0));
}
+//! [5]
-void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect)
+//! [6]
+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.intersected(sceneRect), gradient);
- painter->setBrush(Qt::NoBrush);
- painter->drawRect(sceneRect);
+ Q_UNUSED(painter);
+
+// // 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);
+//
+//#if !defined(Q_OS_SYMBIAN) && !defined(Q_WS_MAEMO_5)
+// // 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);
+//#endif
}
+//! [6]
+//! [7]
void GraphWidget::scaleView(qreal scaleFactor)
{
- qreal factor = matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
+ qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
if (factor < 0.07 || factor > 100)
return;
scale(scaleFactor, scaleFactor);
}
+//! [7]
+
+void GraphWidget::shuffle()
+{
+ foreach (QGraphicsItem *item, scene()->items()) {
+ if (qgraphicsitem_cast<Node *>(item))
+ item->setPos(-150 + qrand() % 300, -150 + qrand() % 300);
+ }
+}
+
+void GraphWidget::zoomIn()
+{
+ scaleView(qreal(1.2));
+}
+
+void GraphWidget::zoomOut()
+{
+ scaleView(1 / qreal(1.2));
+}
+
// Find node of the function
Node* GraphWidget::findNode(const TDF_Label& L)
if (myNbThreads > 3)
myThread4->setThreadIndex(4);
+ myThread1->setMutex(&myMutex);
+ if (myNbThreads > 1)
+ myThread2->setMutex(&myMutex);
+ if (myNbThreads > 2)
+ myThread3->setMutex(&myMutex);
+ if (myNbThreads > 3)
+ myThread4->setMutex(&myMutex);
+
QThread::Priority priority = QThread::LowestPriority;
if (!myThread1->isRunning())
myThread1->start(priority);
myThread4->setPriority(priority);
break;
}
-}
\ No newline at end of file
+}
class Node;
+//! [0]
class GraphWidget : public QGraphicsView
{
Q_OBJECT
public:
- GraphWidget(QWidget* parent);
- ~GraphWidget();
+ GraphWidget(QWidget *parent = 0);
+ ~GraphWidget();
+
+ void itemMoved();
bool createModel(const Handle(TDocStd_Document)& doc);
Handle(TDocStd_Document) getDocument() { return myDocument; }
void setFinished();
bool isFinished();
+public slots:
+ void shuffle();
+ void zoomIn();
+ void zoomOut();
+
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;
+
+private:
+ Standard_Mutex myMutex;
Handle(TDocStd_Document) myDocument;
int myNbThreads;
FThread* myThread1;
FThread* myThread4;
int myNbFinishedThreads;
};
+//! [0]
#endif
// Create a new document
createDefaultModel1();
+ graph->setNbThreads(4);
}
Handle(AppStd_Application) MainWindow::getApplication()
{
bool ok;
int nb = QInputDialog::getInt(this, tr("Number of threads"), tr("(1 - 4): "),
- graph->getNbThreads(), 1, 4, 1, &ok);
+ graph->getNbThreads(), 1, 4, 1, &ok);
if (ok)
graph->setNbThreads(nb);
}
Handle(TDocStd_Document) doc;
app->NewDocument("XmlOcaf", doc);
TDF_Label mainLabel = doc->Main();
+ mainLabel.ForgetAllAttributes(true);
// Initialize function drivers
TFunction_DriverTable::Get()->AddDriver(SimpleDriver::GetID(), new SimpleDriver());
Handle(AppStd_Application) app = MainWindow::getApplication();
Handle(TDocStd_Document) doc;
app->NewDocument("BinOcaf", doc);
- //app->Open("W:\\TestFM\\model2.cbf", doc);
TDF_Label mainLabel = doc->Main();
+ mainLabel.ForgetAllAttributes(true);
// Initialize function drivers
TFunction_DriverTable::Get()->AddDriver(PointDriver::GetID(), new PointDriver());
#include <TDataStd_Name.hxx>
#include <TDataStd_Tick.hxx>
+//! [0]
Node::Node(GraphWidget *graphWidget)
: graph(graphWidget)
{
setFlag(ItemIsMovable);
- setZValue(1);
+ setFlag(ItemSendsGeometryChanges);
+ setCacheMode(DeviceCoordinateCache);
+ setZValue(-1);
}
+//! [0]
void Node::setFunction(const TDF_Label& func)
{
return myFunction;
}
+//! [1]
void Node::addEdge(Edge *edge)
{
edgeList << edge;
{
return edgeList;
}
+//! [1]
+//! [2]
+void Node::calculateForces()
+{
+ if (!scene() || scene()->mouseGrabberItem() == this) {
+ newPos = pos();
+ return;
+ }
+//! [2]
+
+//! [3]
+ // 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;
+
+ QPointF vec = mapToItem(node, 0, 0);
+ qreal dx = vec.x();
+ qreal dy = vec.y();
+ double l = 2.0 * (dx * dx + dy * dy);
+ if (l > 0) {
+ xvel += (dx * 150.0) / l;
+ yvel += (dy * 150.0) / l;
+ }
+ }
+//! [3]
+
+//! [4]
+ // Now subtract all forces pulling items together
+ double weight = (edgeList.size() + 1) * 10;
+ foreach (Edge *edge, edgeList) {
+ QPointF vec;
+ if (edge->sourceNode() == this)
+ vec = mapToItem(edge->destNode(), 0, 0);
+ else
+ vec = mapToItem(edge->sourceNode(), 0, 0);
+ xvel -= vec.x() / weight;
+ yvel -= vec.y() / weight;
+ }
+//! [4]
+
+//! [5]
+ if (qAbs(xvel) < 0.1 && qAbs(yvel) < 0.1)
+ xvel = yvel = 0;
+//! [5]
+
+//! [6]
+ 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));
+}
+//! [6]
+
+//! [7]
+bool Node::advance()
+{
+ if (newPos == pos())
+ return false;
+
+ setPos(newPos);
+ return true;
+}
+//! [7]
+
+//! [8]
QRectF Node::boundingRect() const
{
+#if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5)
+ // Add some extra space around the circle for easier touching with finger
+ qreal adjust = 30;
+ return QRectF( -10 - adjust, -10 - adjust,
+ 20 + adjust * 2, 20 + adjust * 2);
+#else
qreal adjust = 2;
- return QRectF(-15 - adjust, -15 - adjust,
- 33 + adjust, 33 + adjust);
+ return QRectF( -10 - adjust, -10 - adjust,
+ 23 + adjust, 23 + adjust);
+#endif
}
+//! [8]
+//! [9]
QPainterPath Node::shape() const
{
QPainterPath path;
- path.addEllipse(-15, -15, 30, 30);
+#if defined(Q_OS_SYMBIAN) || defined(Q_WS_MAEMO_5)
+ // Add some extra space around the circle for easier touching with finger
+ path.addEllipse( -40, -40, 80, 80);
+#else
+ path.addEllipse(-10, -10, 20, 20);
+#endif
return path;
}
+//! [9]
+//! [10]
void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
painter->setPen(Qt::NoPen);
painter->setBrush(Qt::darkGray);
- painter->drawEllipse(-12, -12, 30, 30);
+ painter->drawEllipse(-7, -7, 20, 20);
QColor light_color(Qt::yellow);
TFunction_IFunction iFunc(myFunction);
gradient.setColorAt(1, dark_color);
}
painter->setBrush(gradient);
+
painter->setPen(QPen(Qt::black, 0));
- painter->drawEllipse(-15, -15, 30, 30);
+ painter->drawEllipse(-10, -10, 20, 20);
QString s;
Handle(TDataStd_Name) n;
s = TCollection_AsciiString(n->Get()).ToCString();
painter->drawText(-7, 3, s);
}
+//! [10]
+//! [11]
QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value)
{
switch (change) {
- case ItemPositionChange:
+ case ItemPositionHasChanged:
foreach (Edge *edge, edgeList)
edge->adjust();
+ //graph->itemMoved();
break;
default:
break;
return QGraphicsItem::itemChange(change, value);
}
+//! [11]
+//! [12]
void Node::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
update();
update();
QGraphicsItem::mouseReleaseEvent(event);
}
+//! [12]
class Edge;
class GraphWidget;
+QT_BEGIN_NAMESPACE
class QGraphicsSceneMouseEvent;
+QT_END_NAMESPACE
+//! [0]
class Node : public QGraphicsItem
{
public:
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);
GraphWidget *graph;
TDF_Label myFunction;
};
+//! [0]
#endif