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 | |
55 | GraphWidget::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 | |
74 | GraphWidget::~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 | |
98 | bool 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 | |
181 | void GraphWidget::wheelEvent(QWheelEvent *event) |
182 | { |
183 | scaleView(pow((double)2, -event->delta() / 240.0)); |
184 | } |
185 | |
186 | void 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); |
caee72a9 |
203 | painter->fillRect(rect.intersected(sceneRect), gradient); |
aff5997d |
204 | painter->setBrush(Qt::NoBrush); |
205 | painter->drawRect(sceneRect); |
206 | } |
207 | |
208 | void 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 |
218 | Node* 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 | |
233 | void 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 | |
293 | void 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 | |
327 | int GraphWidget::getNbThreads() |
328 | { |
329 | return myNbThreads; |
330 | } |
331 | |
332 | void GraphWidget::setFinished() |
333 | { |
334 | myNbFinishedThreads++; |
335 | } |
336 | |
337 | bool GraphWidget::isFinished() |
338 | { |
339 | return myNbThreads == myNbFinishedThreads ; |
340 | } |
341 | |
342 | void 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 | |
374 | void 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 | } |