Salome HOME
Update copyright information
[modules/visu.git] / src / VISUGUI / VisuGUI_FindPane.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 //  VISU VISUGUI : GUI of VISU component
21 //  File   : VisuGUI_FindPane.cxx
22 //  Author : Oleg Uvarov
23 //  Module : VISU
24 //
25 #include "VisuGUI_FindPane.h"
26 #include "VisuGUI_Tools.h"
27
28 #include "VISU_Actor.h"
29 #include "VISU_Event.h"
30 #include "VISU_GaussPtsAct.h"
31
32 #include "VISU_IDMapper.hxx"
33 #include "VISU_GaussPointsPL.hxx"
34 #include "VISU_ConvertorUtils.hxx"
35
36 #include "SUIT_MessageBox.h"
37 #include "SUIT_ResourceMgr.h"
38
39 #include <QComboBox>
40 #include <QLabel>
41 #include <QLayout>
42 #include <QListWidget>
43 #include <QLineEdit>
44 #include <QToolButton>
45
46 #include <vtkCellData.h>
47 #include <vtkDataArray.h>
48 #include <vtkDataSet.h>
49 #include <vtkMapper.h>
50 #include <vtkPointData.h>
51
52 #define PAGE_SIZE 10
53
54 VisuGUI_FindPane::VisuGUI_FindPane( QWidget* theParent ) :
55   QGroupBox( theParent ),
56   myCurrentPage( 0 ),
57   mySelectionMode( -1 ),
58   myActor( 0 )
59 {
60   setTitle( tr( "FIND_TITLE" ) );
61
62   QGridLayout* aTopLayout = new QGridLayout( this );
63
64   QLabel* aConditionLabel = new QLabel( tr( "CONDITION" ), this );
65
66   myConditionBox = new QComboBox( this );
67   myConditionBox->addItems( QStringList()
68                             << tr( "MINIMUM" )
69                             << tr( "MAXIMUM" )
70                             << "="
71                             << "<="
72                             << ">="
73                             << tr( "BETWEEN" ) );
74
75   connect( myConditionBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( onConditionChanged( int ) ) );
76
77   QDoubleValidator* aDoubleValidator = new QDoubleValidator( this );
78
79   myLeftValue = new QLineEdit( this );
80   myLeftValue->setValidator( aDoubleValidator );
81
82   myDashLabel = new QLabel( "-", this );
83
84   myRightValue = new QLineEdit( this );
85   myRightValue->setValidator( aDoubleValidator );
86
87   QToolButton* anApplyBtn = new QToolButton( this );
88   anApplyBtn->setIcon( VISU::GetResourceMgr()->loadPixmap( "VISU", tr( "ICON_APPLY" ) ) );
89   connect( anApplyBtn, SIGNAL( clicked() ), this, SLOT( onApply() ) );
90
91
92   QWidget* anIdsWidget = new QWidget( this );
93   QGridLayout* anIdsLayout = new QGridLayout( anIdsWidget );
94   anIdsLayout->setMargin( 0 );
95
96   myIdsListWidget = new QListWidget( anIdsWidget );
97   myIdsListWidget->setFlow( QListView::LeftToRight );
98   myIdsListWidget->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
99   myIdsListWidget->setFixedHeight( 45 );
100
101   connect( myIdsListWidget, SIGNAL( itemSelectionChanged() ), this, SLOT( onIdChanged() ) );
102
103   myPageLabel = new QLabel( anIdsWidget );
104   myPageLabel->setAlignment( Qt::AlignHCenter );
105
106   myPrevBtn = new QToolButton( anIdsWidget );
107   myPrevBtn->setIcon( VISU::GetResourceMgr()->loadPixmap( "VISU", tr( "ICON_SLIDER_PREVIOUS" ) ) );
108   connect( myPrevBtn, SIGNAL( clicked() ), this, SLOT( onPrevPage() ) );
109
110   myNextBtn = new QToolButton( anIdsWidget );
111   myNextBtn->setIcon( VISU::GetResourceMgr()->loadPixmap( "VISU", tr( "ICON_SLIDER_NEXT" ) ) );
112   connect( myNextBtn, SIGNAL( clicked() ), this, SLOT( onNextPage() ) );
113
114   anIdsLayout->addWidget( myIdsListWidget, 0, 0, 2, 1 );
115   anIdsLayout->addWidget( myPageLabel,     0, 1, 1, 2 );
116   anIdsLayout->addWidget( myPrevBtn,       1, 1 );
117   anIdsLayout->addWidget( myNextBtn,       1, 2 );
118
119
120   aTopLayout->addWidget( aConditionLabel, 0, 0, 1, 5 );
121   aTopLayout->addWidget( myConditionBox,  1, 0 );
122   aTopLayout->addWidget( myLeftValue,     1, 1 );
123   aTopLayout->addWidget( myDashLabel,     1, 2 );
124   aTopLayout->addWidget( myRightValue,    1, 3 );
125   aTopLayout->addWidget( anApplyBtn,      1, 4 );
126   aTopLayout->addWidget( anIdsWidget,     2, 0, 1, 5 );
127
128   onConditionChanged( 0 );
129
130   setSelectionMode( ActorSelection );
131 }
132
133 VisuGUI_FindPane::~VisuGUI_FindPane()
134 {
135 }
136
137 void VisuGUI_FindPane::setSelectionMode( const Selection_Mode theSelectionMode )
138 {
139   if( mySelectionMode != theSelectionMode )
140     clearIds();
141
142   mySelectionMode = theSelectionMode;
143   setEnabled( mySelectionMode != ActorSelection );
144 }
145
146
147 void VisuGUI_FindPane::setActor( VISU_Actor* theActor )
148 {
149   if( myActor != theActor )
150     clearIds();
151
152   myActor = theActor;
153 }
154
155 void VisuGUI_FindPane::onConditionChanged( int theId )
156 {
157   myLeftValue->setEnabled( theId >= 2 );
158   myDashLabel->setEnabled( theId == 5 );
159   myRightValue->setEnabled( theId == 5 );
160 }
161
162 void VisuGUI_FindPane::onApply()
163 {
164   if( !isValid() )
165   {
166     SUIT_MessageBox::warning( this, tr( "WRN_VISU" ), tr( "INCORRECT_VALUES" ) );
167     return;
168   }
169
170   myIdsListWidget->clear();
171
172   if( !myActor )
173     return;
174
175   vtkDataSet* aDataSet = myActor->GetInput();
176
177   vtkDataArray* aScalars = 0;
178   if( mySelectionMode == NodeSelection )
179     aScalars = aDataSet->GetPointData()->GetScalars();
180   else if( mySelectionMode == CellSelection )
181     aScalars = aDataSet->GetCellData()->GetScalars();
182   else if( mySelectionMode == GaussPointSelection )
183   {
184     if( VISU_GaussPtsAct* aGaussPtsAct = dynamic_cast<VISU_GaussPtsAct*>( myActor ) )
185       aScalars = aGaussPtsAct->GetInput()->GetPointData()->GetScalars();
186   }
187
188
189   if( !aScalars )
190     return;
191
192   int aCondition = myConditionBox->currentIndex();
193   double aLeftValue = myLeftValue->text().toDouble();
194   double aRightValue = myRightValue->text().toDouble();
195
196   myIdsList.clear();
197
198   double eps = 1.0 / VTK_LARGE_FLOAT;
199
200   double anExtremum = 0;
201   if( aCondition == 0 )
202     anExtremum = VTK_LARGE_FLOAT;
203   else if( aCondition == 1 )
204     anExtremum = -VTK_LARGE_FLOAT;
205
206   for( int aVTKId = 0, aNbVal = aScalars->GetNumberOfTuples(); aVTKId < aNbVal; aVTKId++ )
207   {
208     double aValue = *aScalars->GetTuple( aVTKId );
209
210     TFindId anId( -1, -1 );
211     if( mySelectionMode == NodeSelection )
212       anId.first = VISU::GetNodeObjID( aDataSet, aVTKId );
213     else if( mySelectionMode == CellSelection )
214       anId.first = VISU::GetElemObjID( aDataSet, aVTKId );
215     else if( mySelectionMode == GaussPointSelection )
216     {
217       if( VISU_GaussPtsAct* aGaussPtsAct = dynamic_cast<VISU_GaussPtsAct*>( myActor ) )
218       {
219         VISU::TGaussPointID aGaussPointID = aGaussPtsAct->GetGaussPointsPL()->GetObjID( aVTKId );
220         anId.first = aGaussPointID.first;
221         anId.second = aGaussPointID.second;
222       }
223     }
224     //printf( "(%d) <%d - %d> %f\n", aVTKId, anId.first, anId.second, aValue );
225
226     if( anId.first < 0 ||
227         anId.second < 0 && mySelectionMode == GaussPointSelection )
228       continue;
229
230     bool ok = false;
231     switch( aCondition )
232     {
233     case 0: // Minimum
234       ok = ( aValue - anExtremum ) < eps;
235       break;
236     case 1: // Maximum
237       ok = ( aValue - anExtremum ) > -eps;
238       break;
239     case 2: // =
240       ok = fabs( aValue - aLeftValue ) < eps;
241       break;
242     case 3: // <=
243       ok = ( aValue - aLeftValue ) < eps;
244       break;
245     case 4: // >=
246       ok = ( aValue - aLeftValue ) > -eps;
247       break;
248     case 5: // Between
249       ok = ( aValue - aLeftValue ) > -eps && ( aValue - aRightValue ) < eps;
250       break;
251     default:
252       ok = true;
253       break;
254     }
255
256     if( ok )
257     {
258       if( aCondition <= 1 && fabs( aValue - anExtremum ) > eps )
259       {
260         anExtremum = aValue;
261         myIdsList.clear();
262       }
263       if( !myIdsList.contains( anId ) )
264         myIdsList.append( anId );
265     }
266   }
267
268   qSort( myIdsList );
269
270   myCurrentPage = 0;
271   displayIds();
272 }
273
274 void VisuGUI_FindPane::onIdChanged()
275 {
276   int aFirstId = -1, aSecondId = -1;
277
278   QList<QListWidgetItem*> aSelectedItems = myIdsListWidget->selectedItems();
279   if( aSelectedItems.size() == 1 )
280   {
281     QString aStr = aSelectedItems.first()->text();
282
283     bool ok = false;
284     aFirstId = aStr.toInt( &ok );
285     if( !ok ) // try to parse the string as a pair of ids - "[aFirstId aSecondId]"
286     {
287       aStr.remove( '[' );
288       aStr.remove( ']' );
289       aFirstId = aStr.section( ' ', 0, 0 ).toInt( &ok );
290       if( !ok )
291         aFirstId = -1;
292       else
293       {
294         ok = false;
295         aSecondId = aStr.section( ' ', 1, 1 ).toInt( &ok );
296         if( !ok )
297           aSecondId = -1;
298       }
299     }
300   }
301
302   emit idChanged( aFirstId, aSecondId );
303 }
304
305 void VisuGUI_FindPane::onPrevPage()
306 {
307   myCurrentPage--;
308   displayIds();
309 }
310
311 void VisuGUI_FindPane::onNextPage()
312 {
313   myCurrentPage++;
314   displayIds();
315 }
316
317 bool VisuGUI_FindPane::isValid() const
318 {
319   bool ok = false;;
320   double aLeftValue = myLeftValue->text().toDouble( &ok );
321   if( myLeftValue->isEnabled() && !ok )
322     return false;
323
324   ok = false;
325   double aRightValue = myRightValue->text().toDouble( &ok );
326   if( myRightValue->isEnabled() && ( !ok || aRightValue < aLeftValue ) )
327     return false;
328
329   return true;
330 }
331
332 void VisuGUI_FindPane::clearIds()
333 {
334   myIdsList.clear();
335   myCurrentPage = 0;
336
337   displayIds();
338 }
339
340 void VisuGUI_FindPane::displayIds()
341 {
342   myIdsListWidget->clear();
343
344   int aSize = myIdsList.size();
345
346   myPrevBtn->setEnabled( myCurrentPage != 0 );
347   myNextBtn->setEnabled( ( myCurrentPage + 1 ) * PAGE_SIZE < aSize );
348   myPageLabel->setText( QString( "Page %1/%2" )
349                         .arg( aSize > 0 ? myCurrentPage + 1 : 0 )
350                         .arg( aSize > 0 ? ( aSize - 1 ) / PAGE_SIZE + 1 : 0 ) );
351
352   int aFirstIndex = myCurrentPage * PAGE_SIZE;
353   int aLastIndex = aFirstIndex + PAGE_SIZE - 1;
354   if( aLastIndex >= aSize )
355     aLastIndex = aSize - 1;
356
357   for( int anIndex = aFirstIndex; anIndex <= aLastIndex; anIndex++ )
358   {
359     TFindId anId = myIdsList[ anIndex ];
360     int aFirstId = anId.first, aSecondId = anId.second;
361     QString aStr = aSecondId < 0 ?
362       QString( "%1" ).arg( aFirstId ) :
363       QString( "[%1 %2]" ).arg( aFirstId ).arg( aSecondId );
364     myIdsListWidget->addItem( aStr );
365   }
366 }