]> OCCT Git - occt.git/commitdiff
0029750: Samples - function arrows are not updated by moving a node in FuncDemo qt... IR-2020-12-25
authorvro <vro@opencascade.com>
Thu, 17 Dec 2020 10:17:46 +0000 (13:17 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 25 Dec 2020 14:08:25 +0000 (17:08 +0300)
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).

21 files changed:
samples/qt/FuncDemo/custom.bat
samples/qt/FuncDemo/src/BaseDriver.cpp
samples/qt/FuncDemo/src/BaseDriver.h
samples/qt/FuncDemo/src/CircleDriver.h
samples/qt/FuncDemo/src/ConeDriver.h
samples/qt/FuncDemo/src/CylinderDriver.h
samples/qt/FuncDemo/src/FThread.cpp
samples/qt/FuncDemo/src/FThread.h
samples/qt/FuncDemo/src/PointDriver.cpp
samples/qt/FuncDemo/src/PointDriver.h
samples/qt/FuncDemo/src/PrismDriver.h
samples/qt/FuncDemo/src/ShapeSaverDriver.cpp
samples/qt/FuncDemo/src/ShapeSaverDriver.h
samples/qt/FuncDemo/src/SimpleDriver.h
samples/qt/FuncDemo/src/edge.cpp
samples/qt/FuncDemo/src/edge.h
samples/qt/FuncDemo/src/graphwidget.cpp
samples/qt/FuncDemo/src/graphwidget.h
samples/qt/FuncDemo/src/mainwindow.cpp
samples/qt/FuncDemo/src/node.cpp
samples/qt/FuncDemo/src/node.h

index 115ac2c09f5c344ed5416b205a759a058fc32d3e..38728c3ad680e75392098b50be70d371e14af017 100644 (file)
@@ -1,3 +1,3 @@
 @echo off
 rem Define QTDIR variable
-set QTDIR=
+set QTDIR=%PRODUCTS_PATH%/qt486-vc10-32
index f42552e013015feb0fa0823a1ca2fe9ce4069665..2d34a6973ae8e496f65c8a29f498a3bed7329219 100644 (file)
@@ -36,7 +36,6 @@ void BaseDriver::Arguments(TDF_LabelList& args) const
     }
 }
 
-
 // Returns the results of the function
 void BaseDriver::Results(TDF_LabelList& res) const
 {
@@ -50,6 +49,12 @@ 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
 {
index ab23adb858da9d687132716e79602d177bc077a4..c5c669c42cbbcb7c15b92229df8e530b3304fbb4 100644 (file)
@@ -5,14 +5,11 @@
 #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)
 
@@ -30,10 +27,16 @@ public:
        // 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_)
index 11d55c274ebbbe6eea9a20ada6b0f1d1ddbb3e36..eb2c385650fcedda1b4420bcc8ee89f4d1a1ee29 100644 (file)
@@ -5,10 +5,6 @@
 #if !defined(_CIRCLEDRIVER_H_)
 #define _CIRCLEDRIVER_H_
 
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
 #include "BaseDriver.h"
 
 #include <Standard_DefineHandle.hxx> 
index a7f9439f42831f3ef9951efc2928a57905b0e614..be225b1e15fd7e71d788c16053a3febff8e20072 100644 (file)
@@ -5,10 +5,6 @@
 #if !defined(_CONEDRIVER_H_)
 #define _CONEDRIVER_H_
 
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
 #include "BaseDriver.h"
 
 #include <Standard_DefineHandle.hxx> 
index bfa8ee66d52d12d7d0dcddf8921b63fdc7679b24..287ce87a90233ae176ad63019ee1c4cdf047ad52 100644 (file)
@@ -5,10 +5,6 @@
 #if !defined(_CYLINDERDRIVER_H_)
 #define _CYLINDERDRIVER_H_
 
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
 #include "BaseDriver.h"
 
 #include <Standard_DefineHandle.hxx> 
index c18b7c4fbc65bbde15d09e3e79eb8234c5a0e987..d66d14a4ae77f1675b1fe871821a2333f5d3e4bf 100644 (file)
@@ -1,5 +1,6 @@
 #include "FThread.h"
 #include "graphwidget.h"
+#include "BaseDriver.h"
 
 #include <TFunction_Function.hxx>
 #include <TFunction_IFunction.hxx>
@@ -39,6 +40,11 @@ void FThread::setThreadIndex(const int theIndex)
     this->thread_index = theIndex;
 }
 
+void FThread::setMutex(Standard_Mutex* pmutex)
+{
+    this->pmutex = pmutex;
+}
+
 // Returns any free (not executed yet) function
 TDF_Label FThread::getFreeFunction()
 {
@@ -94,12 +100,16 @@ void FThread::run()
         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;
index e7ab7ac0764cae4c425b818fef6f998b7012f5f8..e494b797c086063f8b5289a2efeed345f3b9542a 100644 (file)
@@ -8,6 +8,7 @@
 #include <TFunction_Logbook.hxx>
 #include <TFunction_Iterator.hxx>
 #include <TFunction_Driver.hxx>
+#include <Standard_Mutex.hxx>
 
 class GraphWidget; // shows graphically execution of functions
 
@@ -25,6 +26,7 @@ public:
     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:
 
@@ -35,6 +37,7 @@ private:
 
     TFunction_Iterator itr;
     Handle(TFunction_Logbook) log;
+    Standard_Mutex*    pmutex;
     int                thread_index;
 
     GraphWidget*       graph;
index 3f10412735dc7eb4d5d096fc78c38f09d5d31e3f..03aa733ce86f58ae55a876f1b6141ef706dda8a9 100644 (file)
@@ -47,9 +47,15 @@ Standard_Integer PointDriver::Execute(Handle(TFunction_Logbook)& log) const
     // 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
index 01592374681345aff3339a80102c10131b84aa98..4d6cd1ccba98743887429ef587e68b8fda71c2c9 100644 (file)
@@ -5,10 +5,6 @@
 #if !defined(_PointDRIVER_H_)
 #define _PointDRIVER_H_
 
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
 #include "BaseDriver.h"
 
 #include <Standard_DefineHandle.hxx> 
index 778b1cd92f87f65165c99c58eff22cbeb804ad81..4c2894e5e52151dbbda89ff310628b7e62e75c6a 100644 (file)
@@ -5,10 +5,6 @@
 #if !defined(_PRISMDRIVER_H_)
 #define _PRISMDRIVER_H_
 
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
 #include "BaseDriver.h"
 
 #include <Standard_DefineHandle.hxx> 
index 1f14881b5de89b07c7eef01698204a35ab5d909e..15a39f9279735059825406941fa08624e8649051 100644 (file)
@@ -56,10 +56,14 @@ Standard_Integer ShapeSaverDriver::Execute(Handle(TFunction_Logbook)& log) const
         }
     }
 
-    //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
index 5247949b787949180289da622114cdbb2ba414fd..ddc6b1338de800fb1870cc102148aa0662254286 100644 (file)
@@ -5,10 +5,6 @@
 #if !defined(_SHAPESAVERDRIVER_H_)
 #define _SHAPESAVERDRIVER_H_
 
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
 #include "BaseDriver.h"
 
 #include <Standard_DefineHandle.hxx> 
index a78a065b569d87ed332e98bfd7f1bd4d1ae93680..92b646a049312cf5bc253f93adbd3d2bc1d3866c 100644 (file)
@@ -5,10 +5,6 @@
 #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>
index 983b64a21b74bef504b8dcce4ed1fa1556bacdbd..93a3b029adb99d5505fff810a9098b07d73f02a5 100644 (file)
@@ -50,6 +50,7 @@
 static const double Pi = 3.14159265358979323846264338327950288419717;
 static double TwoPi = 2.0 * Pi;
 
+//! [0]
 Edge::Edge(Node *sourceNode, Node *destNode)
     : arrowSize(10)
 {
@@ -60,7 +61,9 @@ Edge::Edge(Node *sourceNode, Node *destNode)
     dest->addEdge(this);
     adjust();
 }
+//! [0]
 
+//! [1]
 Node *Edge::sourceNode() const
 {
     return source;
@@ -70,7 +73,9 @@ Node *Edge::destNode() const
 {
     return dest;
 }
+//! [1]
 
+//! [2]
 void Edge::adjust()
 {
     if (!source || !dest)
@@ -89,7 +94,9 @@ void Edge::adjust()
         sourcePoint = destPoint = line.p1();
     }
 }
+//! [2]
 
+//! [3]
 QRectF Edge::boundingRect() const
 {
     if (!source || !dest)
@@ -103,7 +110,9 @@ QRectF Edge::boundingRect() const
         .normalized()
         .adjusted(-extra, -extra, extra, extra);
 }
+//! [3]
 
+//! [4]
 void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
 {
     if (!source || !dest)
@@ -112,11 +121,15 @@ void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
     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)
@@ -135,3 +148,4 @@ void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
     painter->drawPolygon(QPolygonF() << line.p1() << sourceArrowP1 << sourceArrowP2);
     painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2);
 }
+//! [6]
index 5662ef00ab0169c3e1dea94e9e6bc8babfd84c35..21bdec02ead830c2968cb84ddf3f3dbe233b2066 100644 (file)
 
 class Node;
 
+//! [0]
 class Edge : public QGraphicsItem
 {
 public:
     Edge(Node *sourceNode, Node *destNode);
 
     Node *sourceNode() const;
-
     Node *destNode() const;
 
     void adjust();
@@ -72,5 +72,6 @@ private:
     QPointF destPoint;
     qreal arrowSize;
 };
+//! [0]
 
 #endif
index 1ee3a6609e1638e25661d8d266fbdee67fb14d85..5c6992f22df00f2fed6bedcdaa919446485e3755 100644 (file)
 #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()
 {
@@ -138,8 +184,8 @@ bool GraphWidget::createModel(const Handle(TDocStd_Document)& doc)
         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;
@@ -163,6 +209,7 @@ bool GraphWidget::createModel(const Handle(TDocStd_Document)& doc)
         if (y > height())
             y = y0;
         fIterator.Next();
+        x = x0 + dx;
     }
 
     // Draw dependencies
@@ -199,41 +246,151 @@ bool GraphWidget::createModel(const Handle(TDocStd_Document)& doc)
     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)
@@ -300,6 +457,14 @@ void GraphWidget::compute()
     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);
@@ -410,4 +575,4 @@ void GraphWidget::slowDownThread(const int thread_index)
         myThread4->setPriority(priority);
         break;
     }
-}
\ No newline at end of file
+}
index d4205e6bc2b96cbaaadbd0278a8730a1de99edcd..7459b337fd4caa73325d13cfddd9807d1fb5a3d9 100644 (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; }
@@ -73,12 +76,25 @@ public:
     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;
@@ -87,5 +103,6 @@ private:
     FThread*                 myThread4;
     int                      myNbFinishedThreads;
 };
+//! [0]
 
 #endif
index f7f5694cec908bf988997c182d637793ae4dcd0f..c86003ad8eeb516c782b26598d3954ea2fc3bed7 100644 (file)
@@ -101,6 +101,7 @@ MainWindow::MainWindow()
 
     // Create a new document
     createDefaultModel1();
+    graph->setNbThreads(4);
 }
 
 Handle(AppStd_Application) MainWindow::getApplication()
@@ -224,7 +225,7 @@ void MainWindow::nbThreads()
 {
     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);
 }
@@ -335,6 +336,7 @@ void MainWindow::createDefaultModel1()
     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());
@@ -423,8 +425,8 @@ void MainWindow::createDefaultModel2()
     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());
index 9271222fbc8419ebc6a2fd9f9b6e6db71c78dcf9..5afd1f022f00f40143e44e8825237c91c985acc1 100644 (file)
 #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)
 {
@@ -71,6 +75,7 @@ const TDF_Label& Node::getFunction() const
     return myFunction;
 }
 
+//! [1]
 void Node::addEdge(Edge *edge)
 {
     edgeList << edge;
@@ -81,26 +86,111 @@ QList<Edge *> Node::edges() const
 {
     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);
@@ -137,8 +227,9 @@ void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
         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;
@@ -146,13 +237,16 @@ void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
         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;
@@ -160,7 +254,9 @@ QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value)
 
     return QGraphicsItem::itemChange(change, value);
 }
+//! [11]
 
+//! [12]
 void Node::mousePressEvent(QGraphicsSceneMouseEvent *event)
 {
     update();
@@ -172,3 +268,4 @@ void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
     update();
     QGraphicsItem::mouseReleaseEvent(event);
 }
+//! [12]
index 393cc1f09b6c33fd4c289a222cea080594fd6809..ab56201e6b31ddb3fcd3660bab435933019cd374 100644 (file)
 
 class Edge;
 class GraphWidget;
+QT_BEGIN_NAMESPACE
 class QGraphicsSceneMouseEvent;
+QT_END_NAMESPACE
 
+//! [0]
 class Node : public QGraphicsItem
 {
 public:
@@ -66,12 +69,16 @@ 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);
     
@@ -81,5 +88,6 @@ private:
     GraphWidget *graph;
     TDF_Label myFunction;
 };
+//! [0]
 
 #endif