Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[modules/gui.git] / src / SVTK / SVTK_UpdateRateDlg.cxx
1 //  SALOME VTKViewer : build VTK viewer into Salome desktop
2 //
3 //  Copyright (C) 2003  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 //
23 //
24 //  File   : 
25 //  Author : 
26 //  Module : SALOME
27 //  $Header$
28
29 #include "SVTK_UpdateRateDlg.h"
30
31 #include "SVTK_MainWindow.h"
32 #include "SVTK_RenderWindowInteractor.h"
33 #include "VTKViewer_Algorithm.h"
34 #include "SALOME_Actor.h"
35
36 #include "QtxDblSpinBox.h"
37 #include "QtxAction.h"
38
39 #include <sstream>
40
41 #include <qgroupbox.h>
42 #include <qlabel.h>
43 #include <qpushbutton.h>
44 #include <qlayout.h>
45 #include <qlineedit.h>
46
47 #include <vtkGenericRenderWindowInteractor.h>
48 #include <vtkCallbackCommand.h>
49 #include <vtkRenderWindow.h>
50 #include <vtkRenderer.h>
51 #include <vtkMapper.h>
52 #include <vtkDataSet.h>
53
54 static vtkFloatingPointType OFF_UPDATE_RATE = 0.00001;
55 static vtkFloatingPointType FLOAT_TOLERANCE = 1.0 / VTK_LARGE_FLOAT;
56
57 using namespace std;
58
59 namespace
60 {
61   //----------------------------------------------------------------------------
62   inline
63   QString 
64   GetUpdateRate(SVTK_RenderWindowInteractor* theRWInteractor)
65   {
66     if(vtkRenderer *aRenderer = theRWInteractor->getRenderer()){
67       vtkFloatingPointType aLastRenderTimeInSeconds = aRenderer->GetLastRenderTimeInSeconds();
68       if(aLastRenderTimeInSeconds > FLOAT_TOLERANCE){
69         std::ostringstream aStr;
70         vtkFloatingPointType aFPS = 1.0 / aLastRenderTimeInSeconds;
71         aStr<<aFPS;
72         return QString(aStr.str().c_str());
73       }
74     }
75     return "Inf";
76   }
77
78
79   //----------------------------------------------------------------------------
80   struct TRenderTimeMultiplier
81   {
82     vtkFloatingPointType myVTKMultiplier;
83     vtkFloatingPointType mySALOMEMultiplier;
84
85     TRenderTimeMultiplier():
86       myVTKMultiplier(0.0),
87       mySALOMEMultiplier(0.0)
88     {}
89
90     void
91     operator()(vtkActor* theActor)
92     {
93       if(theActor->GetVisibility()){
94         myVTKMultiplier += theActor->GetAllocatedRenderTime();
95         if(dynamic_cast<SALOME_Actor*>(theActor))
96           mySALOMEMultiplier += theActor->GetAllocatedRenderTime();
97       }
98     }
99   };
100
101
102   //----------------------------------------------------------------------------
103   inline
104   vtkFloatingPointType 
105   AdjustUpdateRate(SVTK_RenderWindowInteractor* theRWInteractor,
106                    vtkFloatingPointType theUpdateRate)
107   {
108     if(vtkRenderer *aRenderer = theRWInteractor->getRenderer()){
109       if(vtkActorCollection *anActorCollection = aRenderer->GetActors()){
110         TRenderTimeMultiplier aMultiplier;
111         using namespace VTK;
112         aMultiplier = ForEach<vtkActor>(anActorCollection,
113                                         aMultiplier);
114         if(aMultiplier.mySALOMEMultiplier > FLOAT_TOLERANCE)
115           theUpdateRate *= aMultiplier.mySALOMEMultiplier / aMultiplier.myVTKMultiplier;
116       }
117     }
118     return theUpdateRate;
119   }
120
121
122   //----------------------------------------------------------------------------
123   struct TCellsCounter
124   {
125     vtkIdType myCounter;
126     TCellsCounter():
127       myCounter(0)
128     {}
129
130     void
131     operator()(SALOME_Actor* theActor)
132     {
133       if(theActor->GetVisibility()){
134         if(vtkMapper *aMapper = theActor->GetMapper()){
135           if(vtkDataSet *aDataSet = aMapper->GetInput()){
136             myCounter += aDataSet->GetNumberOfCells();
137           }
138         }
139       }
140     }
141   };
142
143
144   //----------------------------------------------------------------------------
145   inline
146   QString 
147   GetNumberOfCells(SVTK_RenderWindowInteractor* theRWInteractor)
148   {
149     if(vtkRenderer *aRenderer = theRWInteractor->getRenderer()){
150       if(vtkActorCollection *anActorCollection = aRenderer->GetActors()){
151         TCellsCounter aCounter;
152         using namespace VTK;
153         aCounter = ForEach<SALOME_Actor>(anActorCollection,
154                                          aCounter);
155         return QString::number(aCounter.myCounter);
156       }
157     }
158     
159     return QString::number(0);
160   }
161 }
162
163 /*!
164   Constructor
165 */
166 SVTK_UpdateRateDlg
167 ::SVTK_UpdateRateDlg(QtxAction* theAction,
168                      SVTK_MainWindow* theParent,
169                      const char* theName):
170   SVTK_DialogBase(theAction,
171                   theParent, 
172                   theName),
173   myPriority(0.0),
174   myEventCallbackCommand(vtkCallbackCommand::New()),
175   myRWInteractor(theParent->GetInteractor()),
176   myAction(theAction)
177 {
178   vtkRenderWindowInteractor* aRWI = myRWInteractor->GetDevice();
179   bool anIsEnabledUpdateRate = false;
180
181   setCaption(tr("DLG_TITLE"));
182   QVBoxLayout* aVBoxLayout = new QVBoxLayout(this, 5, 5);
183   {
184     QGroupBox* aGroupBox = new QGroupBox(tr("INPUT_FRAME_TITLE"), this);
185     aGroupBox->setColumnLayout(0, Qt::Vertical );
186     aGroupBox->layout()->setSpacing( 6 );
187     aGroupBox->layout()->setMargin( 11 );
188
189     aGroupBox->setCheckable(true);
190     aGroupBox->setChecked(anIsEnabledUpdateRate);
191     myIsEnableUpdateRateGroupBox = aGroupBox;
192
193     QGridLayout* aGridLayout = new QGridLayout(aGroupBox->layout());
194     {
195       QLabel* aLabel = new QLabel(tr("DESIRED"), aGroupBox);
196       aLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
197       aGridLayout->addWidget(aLabel, 0, 0);
198
199       QtxDblSpinBox* aDblSpinBox = new QtxDblSpinBox(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       QtxDblSpinBox* aDblSpinBox = new QtxDblSpinBox(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     aGroupBox->setColumnLayout(0, Qt::Vertical );
227     aGroupBox->layout()->setSpacing( 6 );
228     aGroupBox->layout()->setMargin( 11 );
229
230     QGridLayout* aGridLayout = new QGridLayout(aGroupBox->layout());
231     {
232       QLabel* aLabel = new QLabel(tr("CURRENT_FPS"), aGroupBox);
233       aLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
234       aGridLayout->addWidget(aLabel, 0, 0);
235
236       QLineEdit* aLineEdit = new QLineEdit( aGroupBox );
237       aLineEdit->setReadOnly( TRUE );
238       aGridLayout->addWidget(aLineEdit, 0, 1);
239
240       myCurrentUpdateRateLineEdit = aLineEdit;
241       myCurrentUpdateRateLineEdit->setText( GetUpdateRate(myRWInteractor) );
242     }
243     {
244       QLabel* aLabel = new QLabel(tr("NUMBER_CELLS"), aGroupBox);
245       aLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
246       aGridLayout->addWidget(aLabel, 1, 0);
247
248       QLineEdit* aLineEdit = new QLineEdit( aGroupBox );
249       aLineEdit->setReadOnly( TRUE );
250       aGridLayout->addWidget(aLineEdit, 1, 1);
251
252       myNumberOfCellsLineEdit = aLineEdit;
253       myNumberOfCellsLineEdit->setText( GetNumberOfCells(myRWInteractor) );
254     }
255     aVBoxLayout->addWidget(aGroupBox);
256   }
257   {
258     QGroupBox* aGroupBox = new QGroupBox(this);
259     QHBoxLayout* aHBoxLayout = new QHBoxLayout(aGroupBox);
260     aHBoxLayout->setMargin(11);
261     aHBoxLayout->setSpacing(6);
262     {
263       QPushButton* aPushButton = new QPushButton(tr("OK"), aGroupBox);
264       aPushButton->setDefault(TRUE);
265       aPushButton->setAutoDefault(TRUE);
266       aHBoxLayout->addWidget(aPushButton);
267       connect(aPushButton, SIGNAL(clicked()), this, SLOT(onClickOk()));
268     }
269     {
270       QPushButton* aPushButton = new QPushButton(tr("Apply"), aGroupBox);
271       aPushButton->setDefault(TRUE);
272       aPushButton->setAutoDefault(TRUE);
273       aHBoxLayout->addWidget(aPushButton);
274       connect(aPushButton, SIGNAL(clicked()), this, SLOT(onClickApply()));
275     }
276     aHBoxLayout->addStretch();
277     {
278       QPushButton* aPushButton = new QPushButton(tr("Close"), aGroupBox);
279       aPushButton->setDefault(TRUE);
280       aPushButton->setAutoDefault(TRUE);
281       aHBoxLayout->addWidget(aPushButton);
282       connect(aPushButton, SIGNAL(clicked()), this, SLOT(onClickClose()));
283     }
284     aVBoxLayout->addWidget(aGroupBox);
285   }
286
287   if(!anIsEnabledUpdateRate){
288     aRWI->SetDesiredUpdateRate(OFF_UPDATE_RATE);
289     aRWI->SetStillUpdateRate(OFF_UPDATE_RATE);  
290   }
291
292   myEventCallbackCommand->Delete();
293   myEventCallbackCommand->SetClientData(this);
294   myEventCallbackCommand->SetCallback(SVTK_UpdateRateDlg::ProcessEvents);
295   vtkRenderer *aRenderer = myRWInteractor->getRenderer();
296   aRenderer->AddObserver(vtkCommand::EndEvent,
297                          myEventCallbackCommand.GetPointer(), 
298                          myPriority);
299 }
300
301 /*!
302   Destroys the object and frees any allocated resources
303  */
304 SVTK_UpdateRateDlg
305 ::~SVTK_UpdateRateDlg()
306 {
307   // no need to delete child widgets, Qt does it all for us
308 }
309
310 /*!
311   Processes events
312 */
313 void 
314 SVTK_UpdateRateDlg
315 ::ProcessEvents(vtkObject* vtkNotUsed(theObject), 
316                 unsigned long theEvent,
317                 void* theClientData, 
318                 void* vtkNotUsed(theCallData))
319 {
320   SVTK_UpdateRateDlg* self = reinterpret_cast<SVTK_UpdateRateDlg*>(theClientData);
321
322   if(theEvent == vtkCommand::EndEvent){
323     self->myCurrentUpdateRateLineEdit->setText( GetUpdateRate(self->myRWInteractor) );
324     self->myNumberOfCellsLineEdit->setText( GetNumberOfCells(self->myRWInteractor) );
325   }
326 }
327
328 /*!
329   Update
330 */
331 void 
332 SVTK_UpdateRateDlg
333 ::Update()
334 {
335   vtkRenderWindowInteractor* aRWI = myRWInteractor->GetDevice();
336
337   vtkFloatingPointType anUpdateRate;
338   if(myIsEnableUpdateRateGroupBox->isChecked()){
339     anUpdateRate = AdjustUpdateRate(myRWInteractor,myDesiredUpdateRateSblSpinBox->value());
340     aRWI->SetDesiredUpdateRate(anUpdateRate);
341     anUpdateRate = AdjustUpdateRate(myRWInteractor,myStillUpdateRateSblSpinBox->value());
342     aRWI->SetStillUpdateRate(anUpdateRate);
343   }else{
344     aRWI->SetDesiredUpdateRate(OFF_UPDATE_RATE);
345     aRWI->SetStillUpdateRate(OFF_UPDATE_RATE);
346   }
347
348   myRWInteractor->getRenderWindow()->Render();
349 }
350
351 /*!
352   SLOT on OK clicked
353 */
354 void 
355 SVTK_UpdateRateDlg
356 ::onClickOk()
357 {
358   Update();
359   onClickClose();
360 }
361
362 /*!
363   SLOT on Apply clicked
364 */
365 void
366 SVTK_UpdateRateDlg
367 ::onClickApply()
368 {
369   Update();
370 }
371
372 /*!
373   SLOT on Close clicked
374 */
375 void 
376 SVTK_UpdateRateDlg
377 ::onClickClose()
378 {
379   reject();
380 }