0029559: Samples - wrong copyright statement in FuncDemo
[occt.git] / samples / qt / FuncDemo / src / graphwidget.cpp
CommitLineData
aff5997d 1/****************************************************************************
2**
967905a3 3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
aff5997d 5**
967905a3 6** This file is part of the examples of the Qt Toolkit.
aff5997d 7**
967905a3 8** $QT_BEGIN_LICENSE:BSD$
9** You may use this file under the terms of the BSD license as follows:
aff5997d 10**
967905a3 11** "Redistribution and use in source and binary forms, with or without
12** modification, are permitted provided that the following conditions are
13** met:
14** * Redistributions of source code must retain the above copyright
15** notice, this list of conditions and the following disclaimer.
16** * Redistributions in binary form must reproduce the above copyright
17** notice, this list of conditions and the following disclaimer in
18** the documentation and/or other materials provided with the
19** distribution.
20** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21** of its contributors may be used to endorse or promote products derived
22** from this software without specific prior written permission.
aff5997d 23**
967905a3 24**
25** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36**
37** $QT_END_LICENSE$
aff5997d 38**
39****************************************************************************/
40
41#include "graphwidget.h"
42#include "edge.h"
43#include "node.h"
44
45#include <QDebug>
46#include <QGraphicsScene>
47#include <QWheelEvent>
48#include <QApplication>
49
50#include <math.h>
51
52#include <TFunction_Iterator.hxx>
53#include <TFunction_IFunction.hxx>
54#include <TFunction_GraphNode.hxx>
55#include <TFunction_Scope.hxx>
56#include <TFunction_DriverTable.hxx>
57#include <TFunction_Driver.hxx>
58#include <TFunction_Function.hxx>
59
60#include <TDataStd_Name.hxx>
61#include <TDF_ChildIterator.hxx>
62#include <TDF_ListIteratorOfLabelList.hxx>
63#include <TColStd_MapIteratorOfMapOfInteger.hxx>
64
65#include "SimpleDriver.h"
66#include "PointDriver.h"
67#include "CircleDriver.h"
68#include "PrismDriver.h"
69#include "ConeDriver.h"
70#include "CylinderDriver.h"
71#include "ShapeSaverDriver.h"
72#include "SimpleDriver.h"
73
74GraphWidget::GraphWidget(QWidget* parent):QGraphicsView(parent),
75 myThread1(0),myThread2(0),myThread3(0),myThread4(0)
76{
77 QGraphicsScene *scene = new QGraphicsScene(this);
78 scene->setItemIndexMethod(QGraphicsScene::NoIndex);
79 scene->setSceneRect(1, 1, parent->width(), parent->height());
80 setScene(scene);
81 setCacheMode(CacheBackground);
82 setRenderHint(QPainter::Antialiasing);
83 setTransformationAnchor(AnchorUnderMouse);
84 setResizeAnchor(AnchorViewCenter);
85
86 scale(0.7, 0.81);
87 setMinimumSize(400, 400);
88 setWindowTitle(tr("Function Mechanism"));
89
90 setNbThreads(1);
91}
92
93GraphWidget::~GraphWidget()
94{
95 if (myThread1)
96 {
97 myThread1->wait();
98 myThread1->deleteLater();
99 }
100 if (myThread2)
101 {
102 myThread2->wait();
103 myThread2->deleteLater();
104 }
105 if (myThread3)
106 {
107 myThread3->wait();
108 myThread3->deleteLater();
109 }
110 if (myThread4)
111 {
112 myThread4->wait();
113 myThread4->deleteLater();
114 }
115}
116
117bool GraphWidget::createModel(const Handle(TDocStd_Document)& doc)
118{
119 myDocument = doc;
120
121 TFunction_Iterator fIterator(myDocument->Main());
122 fIterator.SetUsageOfExecutionStatus(false);
123 Handle(TFunction_Scope) scope = TFunction_Scope::Set(myDocument->Main());
124
125 // Find out the size of the grid: number of functions in X and Y directions
126 int nbx = 0, nby = 0;
127 while (!fIterator.Current().IsEmpty())
128 {
129 const TDF_LabelList& funcs = fIterator.Current();
130 if (funcs.Extent() > nbx)
131 nbx = funcs.Extent();
132 nby++;
133 fIterator.Next();
134 }
135 if (!nbx || !nby)
136 return false;
137
138 // Grid of functions
139 int dx = width() / nbx, dy = height() / nby;
140 int x0 = dx / 2, y0 = dy / 2; // start position
141
142 // Draw functions
143 double x = x0, y = y0;
144 fIterator.Init(myDocument->Main());
145 while (!fIterator.Current().IsEmpty())
146 {
147 const TDF_LabelList& funcs = fIterator.Current();
148 TDF_ListIteratorOfLabelList itrl(funcs);
149 for (; itrl.More(); itrl.Next())
150 {
151 TDF_Label L = itrl.Value();
152 Node *node = new Node(this);
153 node->setFunction(L);
154 scene()->addItem(node);
155 node->setPos(x, y);
156 x += dx;
157 if (x > width())
158 x = x0;
159 }
160 y += dy;
161 if (y > height())
162 y = y0;
163 fIterator.Next();
164 }
165
166 // Draw dependencies
167 fIterator.Init(myDocument->Main());
168 while (!fIterator.Current().IsEmpty())
169 {
170 const TDF_LabelList& funcs = fIterator.Current();
171 TDF_ListIteratorOfLabelList itrl(funcs);
172 for (; itrl.More(); itrl.Next())
173 {
174 TDF_Label L = itrl.Value();
175 Node* node = findNode(L);
176 if (!node)
177 continue;
178
179 // Find backward dependencies of the function
180 TFunction_IFunction iFunc(L);
181 Handle(TFunction_GraphNode) graphNode = iFunc.GetGraphNode();
182 const TColStd_MapOfInteger& prev = graphNode->GetPrevious();
183 TColStd_MapIteratorOfMapOfInteger itrm(prev);
184 for (; itrm.More(); itrm.Next())
185 {
186 const int argID = itrm.Key();
187 const TDF_Label& argL = scope->GetFunction(argID);
188 Node* n = findNode(argL);
189 if (!n)
190 continue;
191 scene()->addItem(new Edge(n, node));
192 }
193 }
194 fIterator.Next();
195 }
196
197 return !myDocument.IsNull();
198}
199
200void GraphWidget::wheelEvent(QWheelEvent *event)
201{
202 scaleView(pow((double)2, -event->delta() / 240.0));
203}
204
205void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect)
206{
207 Q_UNUSED(rect);
208
209 // Shadow
210 QRectF sceneRect = this->sceneRect();
211 QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height());
212 QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5);
213 if (rightShadow.intersects(rect) || rightShadow.contains(rect))
214 painter->fillRect(rightShadow, Qt::darkGray);
215 if (bottomShadow.intersects(rect) || bottomShadow.contains(rect))
216 painter->fillRect(bottomShadow, Qt::darkGray);
217
218 // Fill
219 QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight());
220 gradient.setColorAt(0, Qt::white);
221 gradient.setColorAt(1, Qt::lightGray);
caee72a9 222 painter->fillRect(rect.intersected(sceneRect), gradient);
aff5997d 223 painter->setBrush(Qt::NoBrush);
224 painter->drawRect(sceneRect);
225}
226
227void GraphWidget::scaleView(qreal scaleFactor)
228{
229 qreal factor = matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
230 if (factor < 0.07 || factor > 100)
231 return;
232
233 scale(scaleFactor, scaleFactor);
234}
235
236// Find node of the function
237Node* GraphWidget::findNode(const TDF_Label& L)
238{
239 Node* node = 0;
240 for (int i = 0; i < scene()->items().size(); i++)
241 {
242 Node* n = qgraphicsitem_cast<Node *>(scene()->items().at(i));
243 if (n && n->getFunction() == L)
244 {
245 node = n;
246 break;
247 }
248 }
249 return node;
250}
251
252void GraphWidget::compute()
253{
254 myNbFinishedThreads = 0;
255
256 TFunction_Iterator fIterator(myDocument->Main());
257 fIterator.SetUsageOfExecutionStatus(true);
258
259 myThread1 = new FThread();
260 if (myNbThreads > 1)
261 myThread2 = new FThread();
262 if (myNbThreads > 2)
263 myThread3 = new FThread();
264 if (myNbThreads > 3)
265 myThread4 = new FThread();
266
267 // Logbook
268 Handle(TFunction_Logbook) log = TFunction_Scope::Set(myDocument->Main())->GetLogbook();
269 myThread1->setLogbook(log);
270 if (myNbThreads > 1)
271 myThread2->setLogbook(log);
272 if (myNbThreads > 2)
273 myThread3->setLogbook(log);
274 if (myNbThreads > 3)
275 myThread4->setLogbook(log);
276
277 myThread1->setIterator(fIterator);
278 if (myNbThreads > 1)
279 myThread2->setIterator(fIterator);
280 if (myNbThreads > 2)
281 myThread3->setIterator(fIterator);
282 if (myNbThreads > 3)
283 myThread4->setIterator(fIterator);
284
285 myThread1->setGraph(this);
286 if (myNbThreads > 1)
287 myThread2->setGraph(this);
288 if (myNbThreads > 2)
289 myThread3->setGraph(this);
290 if (myNbThreads > 3)
291 myThread4->setGraph(this);
292
293 myThread1->setThreadIndex(1);
294 if (myNbThreads > 1)
295 myThread2->setThreadIndex(2);
296 if (myNbThreads > 2)
297 myThread3->setThreadIndex(3);
298 if (myNbThreads > 3)
299 myThread4->setThreadIndex(4);
300
301 QThread::Priority priority = QThread::LowestPriority;
302 if (!myThread1->isRunning())
303 myThread1->start(priority);
304 if (myNbThreads > 1 && !myThread2->isRunning())
305 myThread2->start(priority);
306 if (myNbThreads > 2 && !myThread3->isRunning())
307 myThread3->start(priority);
308 if (myNbThreads > 3 && !myThread4->isRunning())
309 myThread4->start(priority);
310}
311
312void GraphWidget::setNbThreads(const int nb)
313{
314 myNbThreads = nb;
315 if (myNbThreads < 4 && myThread4)
316 {
317 myThread4->wait();
318 myThread4->deleteLater();
319 myThread4 = 0;
320 }
321 if (myNbThreads < 3 && myThread3)
322 {
323 myThread3->wait();
324 myThread3->deleteLater();
325 myThread3 = 0;
326 }
327 if (myNbThreads < 2 && myThread2)
328 {
329 myThread2->wait();
330 myThread2->deleteLater();
331 myThread2 = 0;
332 }
333
334 for (int i = 1; i <= myNbThreads; i++)
335 {
336 TFunction_DriverTable::Get()->AddDriver(PointDriver::GetID(), new PointDriver(), i);
337 TFunction_DriverTable::Get()->AddDriver(CircleDriver::GetID(), new CircleDriver(), i);
338 TFunction_DriverTable::Get()->AddDriver(PrismDriver::GetID(), new PrismDriver(), i);
339 TFunction_DriverTable::Get()->AddDriver(ConeDriver::GetID(), new ConeDriver(), i);
340 TFunction_DriverTable::Get()->AddDriver(CylinderDriver::GetID(), new CylinderDriver(), i);
341 TFunction_DriverTable::Get()->AddDriver(ShapeSaverDriver::GetID(), new ShapeSaverDriver(), i);
342 TFunction_DriverTable::Get()->AddDriver(SimpleDriver::GetID(), new SimpleDriver(), i);
343 }
344}
345
346int GraphWidget::getNbThreads()
347{
348 return myNbThreads;
349}
350
351void GraphWidget::setFinished()
352{
353 myNbFinishedThreads++;
354}
355
356bool GraphWidget::isFinished()
357{
358 return myNbThreads == myNbFinishedThreads ;
359}
360
361void GraphWidget::accelerateThread(const int thread_index)
362{
363 bool all_slow = true;
364 if (myThread1 && myThread1->priority() != QThread::LowPriority)
365 all_slow = false;
366 if (all_slow && myThread2 && myThread2->priority() != QThread::LowPriority)
367 all_slow = false;
368 if (all_slow && myThread3 && myThread3->priority() != QThread::LowPriority)
369 all_slow = false;
370 if (all_slow && myThread4 && myThread4->priority() != QThread::LowPriority)
371 all_slow = false;
372 if (!all_slow)
373 return;
374
375 QThread::Priority priority = QThread::NormalPriority;
376 switch (thread_index)
377 {
378 case 1:
379 myThread1->setPriority(priority);
380 break;
381 case 2:
382 myThread2->setPriority(priority);
383 break;
384 case 3:
385 myThread3->setPriority(priority);
386 break;
387 case 4:
388 myThread4->setPriority(priority);
389 break;
390 }
391}
392
393void GraphWidget::slowDownThread(const int thread_index)
394{
395 QThread::Priority priority = QThread::LowPriority;
396 switch (thread_index)
397 {
398 case 1:
399 myThread1->setPriority(priority);
400 break;
401 case 2:
402 myThread2->setPriority(priority);
403 break;
404 case 3:
405 myThread3->setPriority(priority);
406 break;
407 case 4:
408 myThread4->setPriority(priority);
409 break;
410 }
411}