0024665: A sample for advanced function mechanism
[occt.git] / samples / qt / FuncDemo / src / graphwidget.cpp
CommitLineData
aff5997d 1/****************************************************************************
2**
3** Copyright (C) 2006-2007 Trolltech ASA. All rights reserved.
4**
5** This file is part of the example classes of the Qt Toolkit.
6**
7** Licensees holding a valid Qt License Agreement may use this file in
8** accordance with the rights, responsibilities and obligations
9** contained therein. Please consult your licensing agreement or
10** contact sales@trolltech.com if any conditions of this licensing
11** agreement are not clear to you.
12**
13** Further information about Qt licensing is available at:
14** http://www.trolltech.com/products/qt/licensing.html or by
15** contacting info@trolltech.com.
16**
17** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19**
20****************************************************************************/
21
22#include "graphwidget.h"
23#include "edge.h"
24#include "node.h"
25
26#include <QDebug>
27#include <QGraphicsScene>
28#include <QWheelEvent>
29#include <QApplication>
30
31#include <math.h>
32
33#include <TFunction_Iterator.hxx>
34#include <TFunction_IFunction.hxx>
35#include <TFunction_GraphNode.hxx>
36#include <TFunction_Scope.hxx>
37#include <TFunction_DriverTable.hxx>
38#include <TFunction_Driver.hxx>
39#include <TFunction_Function.hxx>
40
41#include <TDataStd_Name.hxx>
42#include <TDF_ChildIterator.hxx>
43#include <TDF_ListIteratorOfLabelList.hxx>
44#include <TColStd_MapIteratorOfMapOfInteger.hxx>
45
46#include "SimpleDriver.h"
47#include "PointDriver.h"
48#include "CircleDriver.h"
49#include "PrismDriver.h"
50#include "ConeDriver.h"
51#include "CylinderDriver.h"
52#include "ShapeSaverDriver.h"
53#include "SimpleDriver.h"
54
55GraphWidget::GraphWidget(QWidget* parent):QGraphicsView(parent),
56 myThread1(0),myThread2(0),myThread3(0),myThread4(0)
57{
58 QGraphicsScene *scene = new QGraphicsScene(this);
59 scene->setItemIndexMethod(QGraphicsScene::NoIndex);
60 scene->setSceneRect(1, 1, parent->width(), parent->height());
61 setScene(scene);
62 setCacheMode(CacheBackground);
63 setRenderHint(QPainter::Antialiasing);
64 setTransformationAnchor(AnchorUnderMouse);
65 setResizeAnchor(AnchorViewCenter);
66
67 scale(0.7, 0.81);
68 setMinimumSize(400, 400);
69 setWindowTitle(tr("Function Mechanism"));
70
71 setNbThreads(1);
72}
73
74GraphWidget::~GraphWidget()
75{
76 if (myThread1)
77 {
78 myThread1->wait();
79 myThread1->deleteLater();
80 }
81 if (myThread2)
82 {
83 myThread2->wait();
84 myThread2->deleteLater();
85 }
86 if (myThread3)
87 {
88 myThread3->wait();
89 myThread3->deleteLater();
90 }
91 if (myThread4)
92 {
93 myThread4->wait();
94 myThread4->deleteLater();
95 }
96}
97
98bool GraphWidget::createModel(const Handle(TDocStd_Document)& doc)
99{
100 myDocument = doc;
101
102 TFunction_Iterator fIterator(myDocument->Main());
103 fIterator.SetUsageOfExecutionStatus(false);
104 Handle(TFunction_Scope) scope = TFunction_Scope::Set(myDocument->Main());
105
106 // Find out the size of the grid: number of functions in X and Y directions
107 int nbx = 0, nby = 0;
108 while (!fIterator.Current().IsEmpty())
109 {
110 const TDF_LabelList& funcs = fIterator.Current();
111 if (funcs.Extent() > nbx)
112 nbx = funcs.Extent();
113 nby++;
114 fIterator.Next();
115 }
116 if (!nbx || !nby)
117 return false;
118
119 // Grid of functions
120 int dx = width() / nbx, dy = height() / nby;
121 int x0 = dx / 2, y0 = dy / 2; // start position
122
123 // Draw functions
124 double x = x0, y = y0;
125 fIterator.Init(myDocument->Main());
126 while (!fIterator.Current().IsEmpty())
127 {
128 const TDF_LabelList& funcs = fIterator.Current();
129 TDF_ListIteratorOfLabelList itrl(funcs);
130 for (; itrl.More(); itrl.Next())
131 {
132 TDF_Label L = itrl.Value();
133 Node *node = new Node(this);
134 node->setFunction(L);
135 scene()->addItem(node);
136 node->setPos(x, y);
137 x += dx;
138 if (x > width())
139 x = x0;
140 }
141 y += dy;
142 if (y > height())
143 y = y0;
144 fIterator.Next();
145 }
146
147 // Draw dependencies
148 fIterator.Init(myDocument->Main());
149 while (!fIterator.Current().IsEmpty())
150 {
151 const TDF_LabelList& funcs = fIterator.Current();
152 TDF_ListIteratorOfLabelList itrl(funcs);
153 for (; itrl.More(); itrl.Next())
154 {
155 TDF_Label L = itrl.Value();
156 Node* node = findNode(L);
157 if (!node)
158 continue;
159
160 // Find backward dependencies of the function
161 TFunction_IFunction iFunc(L);
162 Handle(TFunction_GraphNode) graphNode = iFunc.GetGraphNode();
163 const TColStd_MapOfInteger& prev = graphNode->GetPrevious();
164 TColStd_MapIteratorOfMapOfInteger itrm(prev);
165 for (; itrm.More(); itrm.Next())
166 {
167 const int argID = itrm.Key();
168 const TDF_Label& argL = scope->GetFunction(argID);
169 Node* n = findNode(argL);
170 if (!n)
171 continue;
172 scene()->addItem(new Edge(n, node));
173 }
174 }
175 fIterator.Next();
176 }
177
178 return !myDocument.IsNull();
179}
180
181void GraphWidget::wheelEvent(QWheelEvent *event)
182{
183 scaleView(pow((double)2, -event->delta() / 240.0));
184}
185
186void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect)
187{
188 Q_UNUSED(rect);
189
190 // Shadow
191 QRectF sceneRect = this->sceneRect();
192 QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height());
193 QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5);
194 if (rightShadow.intersects(rect) || rightShadow.contains(rect))
195 painter->fillRect(rightShadow, Qt::darkGray);
196 if (bottomShadow.intersects(rect) || bottomShadow.contains(rect))
197 painter->fillRect(bottomShadow, Qt::darkGray);
198
199 // Fill
200 QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight());
201 gradient.setColorAt(0, Qt::white);
202 gradient.setColorAt(1, Qt::lightGray);
203 painter->fillRect(rect.intersect(sceneRect), gradient);
204 painter->setBrush(Qt::NoBrush);
205 painter->drawRect(sceneRect);
206}
207
208void GraphWidget::scaleView(qreal scaleFactor)
209{
210 qreal factor = matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
211 if (factor < 0.07 || factor > 100)
212 return;
213
214 scale(scaleFactor, scaleFactor);
215}
216
217// Find node of the function
218Node* GraphWidget::findNode(const TDF_Label& L)
219{
220 Node* node = 0;
221 for (int i = 0; i < scene()->items().size(); i++)
222 {
223 Node* n = qgraphicsitem_cast<Node *>(scene()->items().at(i));
224 if (n && n->getFunction() == L)
225 {
226 node = n;
227 break;
228 }
229 }
230 return node;
231}
232
233void GraphWidget::compute()
234{
235 myNbFinishedThreads = 0;
236
237 TFunction_Iterator fIterator(myDocument->Main());
238 fIterator.SetUsageOfExecutionStatus(true);
239
240 myThread1 = new FThread();
241 if (myNbThreads > 1)
242 myThread2 = new FThread();
243 if (myNbThreads > 2)
244 myThread3 = new FThread();
245 if (myNbThreads > 3)
246 myThread4 = new FThread();
247
248 // Logbook
249 Handle(TFunction_Logbook) log = TFunction_Scope::Set(myDocument->Main())->GetLogbook();
250 myThread1->setLogbook(log);
251 if (myNbThreads > 1)
252 myThread2->setLogbook(log);
253 if (myNbThreads > 2)
254 myThread3->setLogbook(log);
255 if (myNbThreads > 3)
256 myThread4->setLogbook(log);
257
258 myThread1->setIterator(fIterator);
259 if (myNbThreads > 1)
260 myThread2->setIterator(fIterator);
261 if (myNbThreads > 2)
262 myThread3->setIterator(fIterator);
263 if (myNbThreads > 3)
264 myThread4->setIterator(fIterator);
265
266 myThread1->setGraph(this);
267 if (myNbThreads > 1)
268 myThread2->setGraph(this);
269 if (myNbThreads > 2)
270 myThread3->setGraph(this);
271 if (myNbThreads > 3)
272 myThread4->setGraph(this);
273
274 myThread1->setThreadIndex(1);
275 if (myNbThreads > 1)
276 myThread2->setThreadIndex(2);
277 if (myNbThreads > 2)
278 myThread3->setThreadIndex(3);
279 if (myNbThreads > 3)
280 myThread4->setThreadIndex(4);
281
282 QThread::Priority priority = QThread::LowestPriority;
283 if (!myThread1->isRunning())
284 myThread1->start(priority);
285 if (myNbThreads > 1 && !myThread2->isRunning())
286 myThread2->start(priority);
287 if (myNbThreads > 2 && !myThread3->isRunning())
288 myThread3->start(priority);
289 if (myNbThreads > 3 && !myThread4->isRunning())
290 myThread4->start(priority);
291}
292
293void GraphWidget::setNbThreads(const int nb)
294{
295 myNbThreads = nb;
296 if (myNbThreads < 4 && myThread4)
297 {
298 myThread4->wait();
299 myThread4->deleteLater();
300 myThread4 = 0;
301 }
302 if (myNbThreads < 3 && myThread3)
303 {
304 myThread3->wait();
305 myThread3->deleteLater();
306 myThread3 = 0;
307 }
308 if (myNbThreads < 2 && myThread2)
309 {
310 myThread2->wait();
311 myThread2->deleteLater();
312 myThread2 = 0;
313 }
314
315 for (int i = 1; i <= myNbThreads; i++)
316 {
317 TFunction_DriverTable::Get()->AddDriver(PointDriver::GetID(), new PointDriver(), i);
318 TFunction_DriverTable::Get()->AddDriver(CircleDriver::GetID(), new CircleDriver(), i);
319 TFunction_DriverTable::Get()->AddDriver(PrismDriver::GetID(), new PrismDriver(), i);
320 TFunction_DriverTable::Get()->AddDriver(ConeDriver::GetID(), new ConeDriver(), i);
321 TFunction_DriverTable::Get()->AddDriver(CylinderDriver::GetID(), new CylinderDriver(), i);
322 TFunction_DriverTable::Get()->AddDriver(ShapeSaverDriver::GetID(), new ShapeSaverDriver(), i);
323 TFunction_DriverTable::Get()->AddDriver(SimpleDriver::GetID(), new SimpleDriver(), i);
324 }
325}
326
327int GraphWidget::getNbThreads()
328{
329 return myNbThreads;
330}
331
332void GraphWidget::setFinished()
333{
334 myNbFinishedThreads++;
335}
336
337bool GraphWidget::isFinished()
338{
339 return myNbThreads == myNbFinishedThreads ;
340}
341
342void GraphWidget::accelerateThread(const int thread_index)
343{
344 bool all_slow = true;
345 if (myThread1 && myThread1->priority() != QThread::LowPriority)
346 all_slow = false;
347 if (all_slow && myThread2 && myThread2->priority() != QThread::LowPriority)
348 all_slow = false;
349 if (all_slow && myThread3 && myThread3->priority() != QThread::LowPriority)
350 all_slow = false;
351 if (all_slow && myThread4 && myThread4->priority() != QThread::LowPriority)
352 all_slow = false;
353 if (!all_slow)
354 return;
355
356 QThread::Priority priority = QThread::NormalPriority;
357 switch (thread_index)
358 {
359 case 1:
360 myThread1->setPriority(priority);
361 break;
362 case 2:
363 myThread2->setPriority(priority);
364 break;
365 case 3:
366 myThread3->setPriority(priority);
367 break;
368 case 4:
369 myThread4->setPriority(priority);
370 break;
371 }
372}
373
374void GraphWidget::slowDownThread(const int thread_index)
375{
376 QThread::Priority priority = QThread::LowPriority;
377 switch (thread_index)
378 {
379 case 1:
380 myThread1->setPriority(priority);
381 break;
382 case 2:
383 myThread2->setPriority(priority);
384 break;
385 case 3:
386 myThread3->setPriority(priority);
387 break;
388 case 4:
389 myThread4->setPriority(priority);
390 break;
391 }
392}