]> SALOME platform Git repositories - modules/gui.git/blob - src/SVTK/SVTK_UpdateRateDlg.cxx
Salome HOME
eaf1be83bdb5a3e60a088afd79be9afbd31bd902
[modules/gui.git] / src / SVTK / SVTK_UpdateRateDlg.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SALOME VTKViewer : build VTK viewer into Salome desktop
23 //  File   : 
24 //  Author : 
25 //  Module : SALOME
26 //  $Header$
27 //
28 #include "SVTK_UpdateRateDlg.h"
29
30 #include "SVTK_ViewWindow.h"
31 #include "SVTK_RenderWindowInteractor.h"
32 #include "VTKViewer_Algorithm.h"
33 #include "SALOME_Actor.h"
34
35 #include "QtxDoubleSpinBox.h"
36 #include "QtxAction.h"
37
38 #include <sstream>
39
40 #include <QGroupBox>
41 #include <QLabel>
42 #include <QPushButton>
43 #include <QGridLayout>
44 #include <QLineEdit>
45
46 #include <vtkGenericRenderWindowInteractor.h>
47 #include <vtkCallbackCommand.h>
48 #include <vtkRenderWindow.h>
49 #include <vtkRenderer.h>
50 #include <vtkMapper.h>
51 #include <vtkDataSet.h>
52
53 static vtkFloatingPointType OFF_UPDATE_RATE = 0.00001;
54 static vtkFloatingPointType FLOAT_TOLERANCE = 1.0 / VTK_LARGE_FLOAT;
55
56 using namespace std;
57
58 namespace
59 {
60   //----------------------------------------------------------------------------
61   inline
62   QString 
63   GetUpdateRate(SVTK_RenderWindowInteractor* theRWInteractor)
64   {
65     if(vtkRenderer *aRenderer = theRWInteractor->getRenderer()){
66       vtkFloatingPointType aLastRenderTimeInSeconds = aRenderer->GetLastRenderTimeInSeconds();
67       if(aLastRenderTimeInSeconds > FLOAT_TOLERANCE){
68         std::ostringstream aStr;
69         vtkFloatingPointType aFPS = 1.0 / aLastRenderTimeInSeconds;
70         aStr<<aFPS;
71         return QString(aStr.str().c_str());
72       }
73     }
74     return "Inf";
75   }
76
77
78   //----------------------------------------------------------------------------
79   struct TRenderTimeMultiplier
80   {
81     vtkFloatingPointType myVTKMultiplier;
82     vtkFloatingPointType mySALOMEMultiplier;
83
84     TRenderTimeMultiplier():
85       myVTKMultiplier(0.0),
86       mySALOMEMultiplier(0.0)
87     {}
88
89     void
90     operator()(vtkActor* theActor)
91     {
92       if(theActor->GetVisibility()){
93         myVTKMultiplier += theActor->GetAllocatedRenderTime();
94         if(dynamic_cast<SALOME_Actor*>(theActor))
95           mySALOMEMultiplier += theActor->GetAllocatedRenderTime();
96       }
97     }
98   };
99
100
101   //----------------------------------------------------------------------------
102   inline
103   vtkFloatingPointType 
104   AdjustUpdateRate(SVTK_RenderWindowInteractor* theRWInteractor,
105                    vtkFloatingPointType theUpdateRate)
106   {
107     if(vtkRenderer *aRenderer = theRWInteractor->getRenderer()){
108       if(vtkActorCollection *anActorCollection = aRenderer->GetActors()){
109         TRenderTimeMultiplier aMultiplier;
110         using namespace VTK;
111         aMultiplier = ForEach<vtkActor>(anActorCollection,
112                                         aMultiplier);
113         if(aMultiplier.mySALOMEMultiplier > FLOAT_TOLERANCE)
114           theUpdateRate *= aMultiplier.mySALOMEMultiplier / aMultiplier.myVTKMultiplier;
115       }
116     }
117     return theUpdateRate;
118   }
119
120
121   //----------------------------------------------------------------------------
122   struct TCellsCounter
123   {
124     vtkIdType myCounter;
125     TCellsCounter():
126       myCounter(0)
127     {}
128
129     void
130     operator()(SALOME_Actor* theActor)
131     {
132       if(theActor->GetVisibility()){
133         if(vtkMapper *aMapper = theActor->GetMapper()){
134           if(vtkDataSet *aDataSet = aMapper->GetInput()){
135             myCounter += aDataSet->GetNumberOfCells();
136           }
137         }
138       }
139     }
140   };
141
142
143   //----------------------------------------------------------------------------
144   inline
145   QString 
146   GetNumberOfCells(SVTK_RenderWindowInteractor* theRWInteractor)
147   {
148     if(vtkRenderer *aRenderer = theRWInteractor->getRenderer()){
149       if(vtkActorCollection *anActorCollection = aRenderer->GetActors()){
150         TCellsCounter aCounter;
151         using namespace VTK;
152         aCounter = ForEach<SALOME_Actor>(anActorCollection,
153                                          aCounter);
154         return QString::number(aCounter.myCounter);
155       }
156     }
157     
158     return QString::number(0);
159   }
160 }
161
162 /*!
163   Constructor
164 */
165 SVTK_UpdateRateDlg
166 ::SVTK_UpdateRateDlg(QtxAction* theAction,
167                      SVTK_ViewWindow* theParent,
168                      const char* theName):
169   SVTK_DialogBase(theAction,
170                   theParent, 
171                   theName),
172   myPriority(0.0),
173   myEventCallbackCommand(vtkCallbackCommand::New()),
174   myRWInteractor(theParent->GetInteractor()),
175   myAction(theAction)
176 {
177   vtkRenderWindowInteractor* aRWI = myRWInteractor->GetDevice();
178   bool anIsEnabledUpdateRate = false;
179
180   setWindowTitle(tr("DLG_TITLE"));
181   QVBoxLayout* aVBoxLayout = new QVBoxLayout(this);
182   aVBoxLayout->setMargin(5);
183   aVBoxLayout->setSpacing(5);
184   {
185     QGroupBox* aGroupBox = new QGroupBox(tr("INPUT_FRAME_TITLE"), this);
186
187     aGroupBox->setCheckable(true);
188     aGroupBox->setChecked(anIsEnabledUpdateRate);
189     myIsEnableUpdateRateGroupBox = aGroupBox;
190
191     QGridLayout* aGridLayout = new QGridLayout(aGroupBox);
192     aGridLayout->setSpacing( 6 );
193     aGridLayout->setMargin( 11 );
194     {
195       QLabel* aLabel = new QLabel(tr("DESIRED"), aGroupBox);
196       aLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
197       aGridLayout->addWidget(aLabel, 0, 0);
198
199       QtxDoubleSpinBox* aDblSpinBox = new QtxDoubleSpinBox(OFF_UPDATE_RATE, VTK_LARGE_FLOAT, 2, aGroupBox);
200       aDblSpinBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
201       aGridLayout->addWidget(aDblSpinBox, 0, 1);
202
203       aDblSpinBox->setValue(aRWI->GetDesiredUpdateRate());
204       aDblSpinBox->setEnabled(anIsEnabledUpdateRate);
205       connect(aGroupBox, SIGNAL(toggled(bool)), aDblSpinBox, SLOT(setEnabled(bool)));
206       myDesiredUpdateRateSblSpinBox = aDblSpinBox;
207     }
208     {
209       QLabel* aLabel = new QLabel(tr("STILL"), aGroupBox);
210       aLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
211       aGridLayout->addWidget(aLabel, 1, 0);
212
213       QtxDoubleSpinBox* aDblSpinBox = new QtxDoubleSpinBox(OFF_UPDATE_RATE, VTK_LARGE_FLOAT, 2, aGroupBox);
214       aDblSpinBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
215       aGridLayout->addWidget(aDblSpinBox, 1, 1);
216
217       aDblSpinBox->setValue(aRWI->GetStillUpdateRate());
218       aDblSpinBox->setEnabled(anIsEnabledUpdateRate);
219       connect(aGroupBox, SIGNAL(toggled(bool)), aDblSpinBox, SLOT(setEnabled(bool)));
220       myStillUpdateRateSblSpinBox = aDblSpinBox;
221     }
222     aVBoxLayout->addWidget(aGroupBox);
223   }
224   {
225     QGroupBox* aGroupBox = new QGroupBox(tr("INFORMATION_FRAME_TITLE"), this);
226     
227     QGridLayout* aGridLayout = new QGridLayout(aGroupBox);
228     aGridLayout->layout()->setSpacing( 6 );
229     aGridLayout->layout()->setMargin( 11 );
230     {
231       QLabel* aLabel = new QLabel(tr("CURRENT_FPS"), aGroupBox);
232       aLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
233       aGridLayout->addWidget(aLabel, 0, 0);
234
235       QLineEdit* aLineEdit = new QLineEdit( aGroupBox );
236       aLineEdit->setReadOnly( TRUE );
237       aGridLayout->addWidget(aLineEdit, 0, 1);
238
239       myCurrentUpdateRateLineEdit = aLineEdit;
240       myCurrentUpdateRateLineEdit->setText( GetUpdateRate(myRWInteractor) );
241     }
242     {
243       QLabel* aLabel = new QLabel(tr("NUMBER_CELLS"), aGroupBox);
244       aLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
245       aGridLayout->addWidget(aLabel, 1, 0);
246
247       QLineEdit* aLineEdit = new QLineEdit( aGroupBox );
248       aLineEdit->setReadOnly( TRUE );
249       aGridLayout->addWidget(aLineEdit, 1, 1);
250
251       myNumberOfCellsLineEdit = aLineEdit;
252       myNumberOfCellsLineEdit->setText( GetNumberOfCells(myRWInteractor) );
253     }
254     aVBoxLayout->addWidget(aGroupBox);
255   }
256   {
257     QGroupBox* aGroupBox = new QGroupBox(this);
258     QHBoxLayout* aHBoxLayout = new QHBoxLayout(aGroupBox);
259     aHBoxLayout->setMargin(11);
260     aHBoxLayout->setSpacing(6);
261     {
262       QPushButton* aPushButton = new QPushButton(tr("OK"), aGroupBox);
263       aPushButton->setDefault(TRUE);
264       aPushButton->setAutoDefault(TRUE);
265       aHBoxLayout->addWidget(aPushButton);
266       connect(aPushButton, SIGNAL(clicked()), this, SLOT(onClickOk()));
267     }
268     {
269       QPushButton* aPushButton = new QPushButton(tr("Apply"), aGroupBox);
270       aPushButton->setDefault(TRUE);
271       aPushButton->setAutoDefault(TRUE);
272       aHBoxLayout->addWidget(aPushButton);
273       connect(aPushButton, SIGNAL(clicked()), this, SLOT(onClickApply()));
274     }
275     aHBoxLayout->addStretch();
276     {
277       QPushButton* aPushButton = new QPushButton(tr("Close"), aGroupBox);
278       aPushButton->setDefault(TRUE);
279       aPushButton->setAutoDefault(TRUE);
280       aHBoxLayout->addWidget(aPushButton);
281       connect(aPushButton, SIGNAL(clicked()), this, SLOT(onClickClose()));
282     }
283     aVBoxLayout->addWidget(aGroupBox);
284   }
285
286   if(!anIsEnabledUpdateRate){
287     aRWI->SetDesiredUpdateRate(OFF_UPDATE_RATE);
288     aRWI->SetStillUpdateRate(OFF_UPDATE_RATE);  
289   }
290
291   myEventCallbackCommand->Delete();
292   myEventCallbackCommand->SetClientData(this);
293   myEventCallbackCommand->SetCallback(SVTK_UpdateRateDlg::ProcessEvents);
294   vtkRenderer *aRenderer = myRWInteractor->getRenderer();
295   aRenderer->AddObserver(vtkCommand::EndEvent,
296                          myEventCallbackCommand.GetPointer(), 
297                          myPriority);
298 }
299
300 /*!
301   Destroys the object and frees any allocated resources
302  */
303 SVTK_UpdateRateDlg
304 ::~SVTK_UpdateRateDlg()
305 {
306   // no need to delete child widgets, Qt does it all for us
307 }
308
309 /*!
310   Processes events
311 */
312 void 
313 SVTK_UpdateRateDlg
314 ::ProcessEvents(vtkObject* vtkNotUsed(theObject), 
315                 unsigned long theEvent,
316                 void* theClientData, 
317                 void* vtkNotUsed(theCallData))
318 {
319   SVTK_UpdateRateDlg* self = reinterpret_cast<SVTK_UpdateRateDlg*>(theClientData);
320
321   if(theEvent == vtkCommand::EndEvent){
322     self->myCurrentUpdateRateLineEdit->setText( GetUpdateRate(self->myRWInteractor) );
323     self->myNumberOfCellsLineEdit->setText( GetNumberOfCells(self->myRWInteractor) );
324   }
325 }
326
327 /*!
328   Update
329 */
330 void 
331 SVTK_UpdateRateDlg
332 ::Update()
333 {
334   vtkRenderWindowInteractor* aRWI = myRWInteractor->GetDevice();
335
336   vtkFloatingPointType anUpdateRate;
337   if(myIsEnableUpdateRateGroupBox->isChecked()){
338     anUpdateRate = AdjustUpdateRate(myRWInteractor,myDesiredUpdateRateSblSpinBox->value());
339     aRWI->SetDesiredUpdateRate(anUpdateRate);
340     anUpdateRate = AdjustUpdateRate(myRWInteractor,myStillUpdateRateSblSpinBox->value());
341     aRWI->SetStillUpdateRate(anUpdateRate);
342   }else{
343     aRWI->SetDesiredUpdateRate(OFF_UPDATE_RATE);
344     aRWI->SetStillUpdateRate(OFF_UPDATE_RATE);
345   }
346
347   myRWInteractor->getRenderWindow()->Render();
348 }
349
350 /*!
351   SLOT on OK clicked
352 */
353 void 
354 SVTK_UpdateRateDlg
355 ::onClickOk()
356 {
357   Update();
358   onClickClose();
359 }
360
361 /*!
362   SLOT on Apply clicked
363 */
364 void
365 SVTK_UpdateRateDlg
366 ::onClickApply()
367 {
368   Update();
369 }
370
371 /*!
372   SLOT on Close clicked
373 */
374 void 
375 SVTK_UpdateRateDlg
376 ::onClickClose()
377 {
378   reject();
379 }