Salome HOME
DCQ : Merge with Ecole_Ete_a6.
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_FilterDlg.cxx
1 //  SMESH SMESHGUI : GUI for SMESH component
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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
21 //
22 //
23 //
24 //  File   : SMESHGUI_FilterDlg.cxx
25 //  Author : Sergey LITONIN
26 //  Module : SMESH
27
28 #include "SMESHGUI.h"
29 #include "SMESHGUI_FilterDlg.h"
30 #include "SMESHGUI_Filter.h"
31 #include "SMESH_Actor.h"
32 #include "VTKViewer_InteractorStyleSALOME.h"
33 #include "VTKViewer_ViewFrame.h"
34 #include "QAD_RightFrame.h"
35 #include "SALOME_ListIteratorOfListIO.hxx"
36 #include "SALOMEGUI_QtCatchCorbaException.hxx"
37
38
39 #include <TColStd_MapOfInteger.hxx>
40
41 #include <qframe.h>
42 #include <qlayout.h>
43 #include <qlineedit.h>
44 #include <qpushbutton.h>
45 #include <qgroupbox.h>
46 #include <qtable.h>
47 #include <qstringlist.h>
48 #include <qlayout.h>
49 #include <qwidgetstack.h>
50 #include <qapplication.h>
51 #include <qcombobox.h>
52 #include <qfontmetrics.h>
53 #include <qmessagebox.h>
54 #include <qlabel.h>
55 #include <qbuttongroup.h>
56 #include <qradiobutton.h>
57 #include <qregexp.h>
58 #include <qlistbox.h>
59 #include <qcheckbox.h>
60
61 #define SPACING 5                  
62 #define MARGIN  10
63
64 static int maxLength( const QStringList& theList, const QFontMetrics& theMetrics )
65 {
66   int aRes = 0;
67   QStringList::const_iterator anIter;
68   for ( anIter = theList.begin(); anIter != theList.end(); ++anIter )
69     aRes = Max( aRes, theMetrics.width( *anIter ) );
70   return aRes; 
71 }
72
73 /*
74   Class       : SMESHGUI_FilterDlg::Table            
75   Description : Table used by this dialog
76 */
77
78 class SMESHGUI_FilterDlg::Table : public QTable
79 {
80 public:
81                           Table( QWidget* parent = 0 );
82                           Table( int numRows, int numCols, QWidget* parent = 0 );
83   virtual                 ~Table();
84
85   void                    SetEditable( const bool state, const int row, const int col );
86   bool                    IsEditable( const int row, const int col ) const;  
87
88   virtual bool            eventFilter( QObject *o, QEvent *e );
89   virtual void            insertRows( int row, int count = 1 );
90   virtual QString         text( int row, int col ) const;
91 };
92
93 SMESHGUI_FilterDlg::Table::Table( QWidget* parent )
94 : QTable( parent, "SMESHGUI_FilterDlg::Table" )
95 {
96 }
97
98 SMESHGUI_FilterDlg::Table::Table( int numRows, int numCols, QWidget* parent )
99 : QTable( numRows, numCols, parent, "SMESHGUI_FilterDlg::Table" )
100 {
101 }
102
103 SMESHGUI_FilterDlg::Table::~Table()
104 {
105 }
106
107 void SMESHGUI_FilterDlg::Table::SetEditable( const bool isEditable, const int row, const int col )
108 {
109   QTableItem* anItem = item( row, col );
110   if( anItem )
111     takeItem( anItem );
112
113   if ( !isEditable )
114   {
115     setItem( row, col, new QTableItem( this, QTableItem::Never, "" ) );
116   }
117   else
118   {
119     setItem( row, col, new QTableItem( this, QTableItem::OnTyping, "" ) );
120   }
121 }
122
123 bool SMESHGUI_FilterDlg::Table::IsEditable( const int row, const int col ) const
124 {
125   QTableItem* anItem = item( row, col );
126   return anItem == 0 || anItem->editType() != QTableItem::Never;
127 }
128
129 void SMESHGUI_FilterDlg::Table::insertRows( int row, int count )
130 {
131   int anEditRow = currEditRow();
132   int anEditCol = currEditCol();
133
134 //  printf( "sln: anEditRow = %d, anEditCol = %d\n", anEditRow, anEditCol );
135
136   if ( anEditRow >= 0 && anEditCol >= 0 )
137     endEdit( anEditRow, anEditCol, true, false );
138
139   QTable::insertRows( row, count );
140 }
141
142 QString SMESHGUI_FilterDlg::Table::text( int row, int col ) const
143 {
144   int anEditRow = currEditRow();
145   int anEditCol = currEditCol();
146
147   if ( anEditRow >= 0 && anEditCol >= 0 && anEditRow == row && anEditCol == col )
148     ((Table*)this)->endEdit( row, col, true, false );
149
150   return QTable::text( row, col );
151 }
152
153 bool SMESHGUI_FilterDlg::Table::eventFilter( QObject *o, QEvent *e )
154 {
155   return QTable::eventFilter( o, e );
156 }
157
158 /*
159   Class       : SMESHGUI_FilterDlg
160   Description : Dialog to specify filters for VTK viewer
161 */
162
163
164 //=======================================================================
165 // name    : SMESHGUI_FilterDlg::SMESHGUI_FilterDlg
166 // Purpose : Constructor
167 //=======================================================================
168 SMESHGUI_FilterDlg::SMESHGUI_FilterDlg( QWidget*          theParent, 
169                                         const int         theType,
170                                         const bool        theModal,
171                                         const char*       theName )
172 : QDialog( theParent, theName, theModal, 
173            WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu )
174 {
175   myType = theType;
176
177   setCaption( tr( "CAPTION" ) );
178
179   QVBoxLayout* aDlgLay = new QVBoxLayout( this, MARGIN, SPACING );
180
181   myMainFrame        = createMainFrame  ( this );
182   QFrame* aBtnFrame  = createButtonFrame( this, theModal );
183
184   aDlgLay->addWidget( myMainFrame );
185   aDlgLay->addWidget( aBtnFrame );
186
187   aDlgLay->setStretchFactor( myMainFrame, 1 );
188
189   Init( myType ); 
190 }
191
192
193 //=======================================================================
194 // name    : SMESHGUI_FilterDlg::createMainFrame
195 // Purpose : Create frame containing dialog's input fields
196 //=======================================================================
197 QFrame* SMESHGUI_FilterDlg::createMainFrame( QWidget* theParent )
198 {
199   QGroupBox* aMainFrame = new QGroupBox( 1, Qt::Horizontal, theParent );
200   aMainFrame->setFrameStyle( QFrame::NoFrame );
201   aMainFrame->setInsideMargin( 0 );
202
203   // filter frame
204
205   QGroupBox* aFilterGrp = new QGroupBox( 1, Qt::Horizontal, tr ( "Filter" ), aMainFrame );
206   QFrame* aFilterFrame = new QFrame( aFilterGrp );
207
208   myTableGrp = new QGroupBox( 1, Qt::Horizontal, aFilterFrame );
209   myTableGrp->setFrameStyle( QFrame::NoFrame );
210   myTableGrp->setInsideMargin( 0 );
211       
212   myTables[ myType ] = createTable( myTableGrp, myType );
213   myAddBtn = new QPushButton( tr( "ADD" ), aFilterFrame );
214   myRemoveBtn = new QPushButton( tr( "REMOVE" ), aFilterFrame );
215   myClearBtn = new QPushButton( tr( "CLEAR" ), aFilterFrame );
216
217   QGridLayout* aLay = new QGridLayout( aFilterFrame, 4, 2, 0, SPACING );
218
219   aLay->addMultiCellWidget( myTableGrp, 0, 3, 0, 0 );
220   aLay->addWidget( myAddBtn, 0, 1 );
221   aLay->addWidget( myRemoveBtn, 1, 1 );
222   aLay->addWidget( myClearBtn, 2, 1 );
223   aLay->setColStretch( 0, 1 );
224   aLay->setColStretch( 1, 0 );
225
226   mySetInViewer = new QCheckBox( tr( "SET_IN_VIEWER" ), aFilterGrp );
227   mySetInViewer->setChecked( true );
228
229   QSpacerItem* aVSpacer = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding );
230   aLay->addItem( aVSpacer, 3, 1 );
231
232   // other controls
233   mySourceGrp = createSourceGroup( aMainFrame );
234   
235   // signals and slots
236   connect( myAddBtn,    SIGNAL( clicked() ), this, SLOT( onAddBtn() ) );
237   connect( myRemoveBtn, SIGNAL( clicked() ), this, SLOT( onRemoveBtn() ) );
238   connect( myClearBtn,  SIGNAL( clicked() ), this, SLOT( onClearBtn() ) );
239
240   return aMainFrame;
241 }
242
243 //=======================================================================
244 // name    : SMESHGUI_FilterDlg::createSourceFrame
245 // Purpose : Create frame containing source radio button
246 //=======================================================================
247 QButtonGroup* SMESHGUI_FilterDlg::createSourceGroup( QWidget* theParent )
248 {
249   QButtonGroup* aGrp = new QButtonGroup( 1, Qt::Vertical, tr( "SOURCE" ), theParent );
250
251   QRadioButton* aMeshBtn = new QRadioButton( tr( "MESH" ), aGrp );
252   QRadioButton* aSelBtn  = new QRadioButton( tr( "SELECTION" ), aGrp );
253   QRadioButton* aGrpBtn  = new QRadioButton( tr( "CURRENT_GROUP" ), aGrp );
254 //  QRadioButton* aNoneBtn = new QRadioButton( tr( "NONE" ), aGrp );
255
256   aGrp->insert( aMeshBtn, Mesh );
257   aGrp->insert( aSelBtn, Selection );
258   aGrp->insert( aGrpBtn, Dialog );
259 //  aGrp->insert( aNoneBtn, None );
260
261   aGrp->setButton( Selection );
262
263   return aGrp;
264 }
265
266 //=======================================================================
267 // name    : SMESHGUI_FilterDlg::createTable
268 // Purpose : Create table
269 //=======================================================================
270 SMESHGUI_FilterDlg::Table* SMESHGUI_FilterDlg::createTable( QWidget*  theParent, 
271                                                             const int theType )
272 {
273   // create table
274   Table* aTable= new Table( 0, 5, theParent );
275
276   QHeader* aHeaders = aTable->horizontalHeader();
277
278   QFontMetrics aMetrics( aHeaders->font() );
279
280   int aLenCr = abs(  maxLength( getCriteria( theType ), aMetrics ) - 
281                      aMetrics.width( tr( "CRITERION" ) ) ) / aMetrics.width( ' ' ) + 5;
282
283   int aLenCo = abs(  maxLength( getCriteria( theType ), aMetrics ) - 
284                      aMetrics.width( tr( "COMPARE" ) ) ) / aMetrics.width( ' ' ) + 5;
285
286   QString aCrStr;
287   aCrStr.fill( ' ', aLenCr );
288   QString aCoStr;
289   aCoStr.fill( ' ', 10 );
290
291   aHeaders->setLabel( 0, tr( "CRITERION" ) + aCrStr );
292   aHeaders->setLabel( 1, tr( "COMPARE" ) + aCoStr );
293   aHeaders->setLabel( 2, tr( "THRESHOLD_VALUE" ) );
294   aHeaders->setLabel( 3, tr( "UNARY" ) );
295   aHeaders->setLabel( 4, tr( "BINARY" ) + "  " );
296
297   // set geometry of the table 
298
299   for ( int i = 0; i <= 4; i++ )
300     aTable->adjustColumn( i );
301
302   aTable->updateGeometry();
303   QSize aSize = aTable->sizeHint();
304   int aWidth = aSize.width();
305   aTable->setMinimumSize( QSize( aWidth, aWidth / 2 ) );
306   aTable->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding) );
307
308   if ( theType == SMESH::EDGE )
309     connect( aTable, SIGNAL( valueChanged( int, int ) ),
310              this, SLOT( onCriterionChanged( int, int ) ) );
311
312   return aTable;
313 }
314
315 //=======================================================================
316 // name    : SMESHGUI_FilterDlg::createButtonFrame
317 // Purpose : Create frame containing buttons
318 //=======================================================================
319 QFrame* SMESHGUI_FilterDlg::createButtonFrame( QWidget* theParent, const bool theModal )
320 {
321   QGroupBox* aGrp = new QGroupBox( 1, Qt::Vertical, theParent );
322  
323   myOkBtn      = new QPushButton( tr( "SMESH_BUT_OK"    ), aGrp );
324   myApplyBtn   = new QPushButton( tr( "SMESH_BUT_APPLY" ), aGrp );
325   QLabel* aLbl = new QLabel( aGrp );
326   myCloseBtn   = new QPushButton( tr( "SMESH_BUT_CANCEL" ), aGrp );
327
328   aLbl->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
329
330   connect( myOkBtn,    SIGNAL( clicked() ), SLOT( onOk() ) );
331   connect( myCloseBtn, SIGNAL( clicked() ), SLOT( onClose() ) ) ;
332   connect( myApplyBtn, SIGNAL( clicked() ), SLOT( onApply() ) );
333
334   if ( theModal )
335     myApplyBtn->hide();
336
337   return aGrp;
338 }
339
340 //=======================================================================
341 // name    : SMESHGUI_FilterDlg::~SMESHGUI_FilterDlg
342 // Purpose : Destructor
343 //=======================================================================
344 SMESHGUI_FilterDlg::~SMESHGUI_FilterDlg()
345 {
346 }
347
348 //=======================================================================
349 // name    : SMESHGUI_FilterDlg::Init
350 // Purpose : Init dialog fields, connect signals and slots, show dialog
351 //=======================================================================
352 void SMESHGUI_FilterDlg::Init( const int theType )
353 {
354   mySourceWg  = 0;
355   mySelection = 0;
356   myType      = theType;
357   myMesh      = SMESH::SMESH_Mesh::_nil();
358
359   // activate corresponding tab
360   if ( !myTables.contains( myType ) )
361     myTables[ myType ] = createTable( myTableGrp, myType );
362
363   TableMap::iterator anIter;
364   for ( anIter = myTables.begin(); anIter != myTables.end(); ++anIter )
365     if ( anIter.key() == theType )
366       anIter.data()->show();
367     else
368       anIter.data()->hide();
369
370   // set caption
371   setCaption(  myType == SMESH::EDGE ? tr( "EDGES_TLT" ) : tr( "FACES_TLT" ) );
372
373   qApp->processEvents();
374   updateGeometry();
375   adjustSize();
376   setEnabled( true );
377
378   mySMESHGUI = SMESHGUI::GetSMESHGUI() ;
379   mySMESHGUI->SetActiveDialogBox( ( QDialog* )this ) ;
380
381   connect( mySMESHGUI, SIGNAL( SignalDeactivateActiveDialog() ), SLOT( onDeactivate() ) );
382   connect( mySMESHGUI, SIGNAL( SignalCloseAllDialogs() ), SLOT( onClose() ) );
383
384   int x, y ;
385   mySMESHGUI->DefineDlgPosition( this, x, y );
386   this->move( x, y );
387
388   this->show();
389
390   return;
391 }
392
393 //=======================================================================
394 // name    : SMESHGUI_FilterDlg::onOk
395 // Purpose : SLOT called when "Ok" button pressed. 
396 //           Assign filters VTK viewer and close dialog
397 //=======================================================================
398 void SMESHGUI_FilterDlg::onOk()
399 {
400   if ( onApply() )
401   {
402     disconnect( mySMESHGUI, 0, this, 0 );
403     mySMESHGUI->ResetState() ;
404     accept();
405   }
406     
407 }
408
409 //=======================================================================
410 // name    : SMESHGUI_FilterDlg::onClose
411 // Purpose : SLOT called when "Close" button pressed. Close dialog
412 //=======================================================================
413 void SMESHGUI_FilterDlg::onClose()
414 {
415   disconnect( mySMESHGUI, 0, this, 0 );
416   mySMESHGUI->ResetState() ;
417   reject() ;
418   return ;
419 }
420
421 //=======================================================================
422 // name    : SMESHGUI_FilterDlg::onDeactivate
423 // Purpose : SLOT called when dialog must be deativated
424 //=======================================================================
425 void SMESHGUI_FilterDlg::onDeactivate()
426 {
427   setEnabled( false );
428 }
429
430 //=======================================================================
431 // name    : SMESHGUI_FilterDlg::enterEvent
432 // Purpose : Event filter
433 //=======================================================================
434 void SMESHGUI_FilterDlg::enterEvent( QEvent* )
435 {
436 //  mySMESHGUI->EmitSignalDeactivateDialog();   
437   setEnabled( true );
438 }
439
440
441 //=================================================================================
442 // function : closeEvent()
443 // purpose  :
444 //=================================================================================
445 void SMESHGUI_FilterDlg::closeEvent( QCloseEvent* e )
446 {
447   onClose() ;
448 }
449
450 //=======================================================================
451 // name    : SMESHGUI_FilterDlg::getCriteria
452 // Purpose : Retrieve list of ids from given widget
453 //=======================================================================
454 void SMESHGUI_FilterDlg::getIdsFromWg( const QWidget* theWg, QValueList<int>& theRes ) const
455 {
456   theRes.clear();
457   if ( theWg == 0 )
458     return;
459
460   if ( theWg->inherits( "QListBox" ) )
461   {
462     QListBox* aListBox = ( QListBox* )theWg;
463     bool b;
464     for ( int i = 0, n = aListBox->count(); i < n; i++ )
465     {
466       int anId = aListBox->text( i ).toInt( &b );
467       if ( b )
468         theRes.append( anId );
469     }
470   }
471   else if ( theWg->inherits( "QLineEdit" ) )
472   {
473     QLineEdit* aLineEdit = ( QLineEdit* )theWg;
474     QString aStr = aLineEdit->text();
475     QRegExp aRegExp( "(\\d+)" );
476     bool b;
477     int aPos = 0;
478     while ( aPos >= 0 )
479     {
480       aPos = aRegExp.search( aStr, aPos );
481       if ( aPos > -1 )
482       {
483         int anId = aRegExp.cap( 1 ).toInt( &b );
484         if ( b )
485           theRes.append( anId );
486         aPos += aRegExp.matchedLength();
487       }
488     }
489   }
490 }
491
492 //=======================================================================
493 // name    : SMESHGUI_FilterDlg::getSelMode
494 // Purpose : Get criteria for specified type
495 //=======================================================================
496 Selection_Mode SMESHGUI_FilterDlg::getSelMode( const int theType ) const
497 {
498   switch ( theType )
499   {
500     case SMESH::NODE   : return NodeSelection;
501     case SMESH::EDGE   : return EdgeSelection;
502     case SMESH::FACE   : return FaceSelection;
503     case SMESH::VOLUME : return VolumeSelection;
504     default            : return ActorSelection;
505   }
506  
507 }
508
509 //=======================================================================
510 // name    : SMESHGUI_FilterDlg::getCriteria
511 // Purpose : Get criteria for specified type
512 //=======================================================================
513 void SMESHGUI_FilterDlg::setIdsToWg( QWidget* theWg, const QValueList<int>& theIds )
514 {
515   if ( theWg == 0 )
516     return;
517     
518   if ( theWg->inherits( "QListBox" ) )
519   {
520     QListBox* aListBox = ( QListBox* )theWg;
521     aListBox->clear();
522     
523     QStringList aStrList;
524     QValueList<int>::const_iterator anIter;
525     for ( anIter = theIds.begin(); anIter != theIds.end(); ++anIter )
526       aStrList.append( QString( "%1" ).arg( *anIter ) );
527
528     aListBox->insertStringList( aStrList );
529   }
530   else if ( theWg->inherits( "QLineEdit" ) )
531   {
532     QLineEdit* aLineEdit = ( QLineEdit* )theWg;
533     QString aStr;
534     QValueList<int>::const_iterator anIter;
535
536     for ( anIter = theIds.begin(); anIter != theIds.end(); ++ anIter )
537       aStr += QString( "%1 " ).arg( *anIter );
538
539     if ( !aStr.isEmpty() )
540       aStr.remove( aStr.length() - 1, 1 );
541
542     aLineEdit->setText( aStr );
543   }
544 }
545
546 //=======================================================================
547 // name    : SMESHGUI_FilterDlg::getCriteria
548 // Purpose : Get criteria for specified type
549 //=======================================================================
550 const QStringList& SMESHGUI_FilterDlg::getCriteria( const int theType ) const
551 {
552   if ( theType == SMESH::EDGE )
553   {
554     static QStringList aCriteria;
555     if ( aCriteria.isEmpty() )
556     {
557       aCriteria.append( tr( "FREE_BORDERS" ) );
558       aCriteria.append( tr( "MULTI_BORDERS" ) );
559       aCriteria.append( tr( "LENGTH" ) );
560     }
561     return aCriteria;
562   }
563   else if ( theType == SMESH::FACE )
564   {
565     static QStringList aCriteria;
566     if ( aCriteria.isEmpty() )
567     {
568       aCriteria.append( tr( "ASPECT_RATIO" ) );
569       aCriteria.append( tr( "WARPING" ) );
570       aCriteria.append( tr( "MINIMUM_ANGLE" ) );
571       aCriteria.append( tr( "TAPER" ) );
572       aCriteria.append( tr( "SKEW" ) );
573       aCriteria.append( tr( "AREA" ) );
574     }
575     return aCriteria;
576   }
577   else
578   {
579     static QStringList aCriteria;
580     return aCriteria;
581   }
582 }
583
584 //=======================================================================
585 // name    : SMESHGUI_FilterDlg::getCompare
586 // Purpose : Get operation of comparison
587 //=======================================================================
588 const QStringList& SMESHGUI_FilterDlg::getCompare () const
589 {
590   static QStringList aList;
591
592   if ( aList.isEmpty() )
593   {
594     aList.append( tr( "LESS_THAN" ) );
595     aList.append( tr( "MORE_THAN" ) );
596     aList.append( tr( "EQUAL_TO" ) );
597   }
598
599   return aList;
600 }
601
602 //=======================================================================
603 // name    : SMESHGUI_FilterDlg::getCriterionItem
604 // Purpose : Get combo table item for criteria of specified type
605 //=======================================================================
606 QTableItem* SMESHGUI_FilterDlg::getCriterionItem( QTable* theParent , const int theType )
607 {
608   return new QComboTableItem( theParent, getCriteria( theType ) );
609 }
610
611 //=======================================================================
612 // name    : SMESHGUI_FilterDlg::getCompareItem
613 // Purpose : Get combo table item for operation of comparision
614 //=======================================================================
615 QTableItem* SMESHGUI_FilterDlg::getCompareItem( QTable* theParent )
616 {
617   return new QComboTableItem( theParent, getCompare() );
618 }
619
620 //=======================================================================
621 // name    : SMESHGUI_FilterDlg::getLogOpItem
622 // Purpose :
623 //=======================================================================
624 QTableItem* SMESHGUI_FilterDlg::getLogOpItem( QTable* theParent )
625 {
626   static QStringList aList;
627   if ( aList.isEmpty() )
628   {
629     aList.append( tr( "AND" ) );
630     aList.append( tr( "OR" ) );
631   }
632
633   return new QComboTableItem( theParent, aList );
634 }
635
636 //=======================================================================
637 // name    : SMESHGUI_FilterDlg::getNotItem
638 // Purpose : Get check table item
639 //=======================================================================
640 QTableItem* SMESHGUI_FilterDlg::getNotItem( QTable* theParent )
641 {
642   return new QCheckTableItem( theParent, tr( "NOT" ) );
643 }
644
645 //=======================================================================
646 // name    : SMESHGUI_FilterDlg::getCurrType
647 // Purpose : Get current entity type
648 //=======================================================================
649 int SMESHGUI_FilterDlg::getCurrType() const
650 {
651   return myType;
652 }
653
654 //=======================================================================
655 // name    : SMESHGUI_FilterDlg::getCriterion
656 // Purpose :
657 //=======================================================================
658 int SMESHGUI_FilterDlg::getCriterion( const int theType, const int theRow ) const
659 {
660   QComboTableItem* anItem = ( QComboTableItem* )myTables[ getCurrType() ]->item( theRow, 0 );
661   return anItem->currentItem();
662 }
663
664 //=======================================================================
665 // name    : SMESHGUI_FilterDlg::addRow
666 // Purpose :
667 //=======================================================================
668 void SMESHGUI_FilterDlg::addRow( Table* theTable, const int theType )
669 {
670   theTable->insertRows( theTable->numRows() );
671   int aCurrRow = theTable->numRows() - 1;
672
673   // Criteria
674   theTable->setItem( aCurrRow, 0, getCriterionItem( theTable, theType ) );
675
676   // Compare
677   theTable->setItem( aCurrRow, 1, getCompareItem( theTable ) );
678
679   //Logical operation NOT
680   theTable->setItem( aCurrRow, 3, getNotItem( theTable ) );
681
682   // Logical binary operation for previous value
683   if ( aCurrRow > 0 )
684     theTable->setItem( aCurrRow - 1, 4, getLogOpItem( theTable ) );
685   theTable->SetEditable( false, aCurrRow, 4 );
686
687   onCriterionChanged( aCurrRow, 0 );
688 }
689
690 //=======================================================================
691 // name    : SMESHGUI_FilterDlg::onAddBtn
692 // Purpose : SLOT. Called then "Add" button pressed.
693 //           Adds new string to table
694 //=======================================================================
695 void SMESHGUI_FilterDlg::onAddBtn()
696 {
697   // QTable
698   int aType = getCurrType();
699   Table* aTable = myTables[ aType ];
700
701   addRow( aTable, aType );
702
703   updateBtnState();
704
705 }
706
707 //=======================================================================
708 // name    : SMESHGUI_FilterDlg::onCriterionChanged()
709 // Purpose : SLOT. Called then contents of table changed
710 //           Provides reaction on change of criterion
711 //=======================================================================
712 void SMESHGUI_FilterDlg::onCriterionChanged( int row, int col )
713 {
714   int aType = getCurrType();
715   if ( aType != SMESH::EDGE || col != 0 )
716     return;
717
718   Table* aTable = myTables[ aType ];
719   QComboTableItem* aCompareItem = (QComboTableItem*)aTable->item( row, 1 );
720
721   if ( getCriterion( aType, row ) != FreeBorders )
722   {
723     if ( aCompareItem->count() == 0 )
724       aCompareItem->setStringList( getCompare() );
725
726     QString aText = aTable->text( row, 2 );
727     aTable->SetEditable( true, row, 2 );
728     aTable->setText( row, 2, aText );
729   }
730   else
731   {
732     if ( aCompareItem->count() > 0 )
733       aCompareItem->setStringList( QStringList() );
734     aTable->SetEditable( false, row, 2 );
735   }
736 }
737
738 //=======================================================================
739 // name    : SMESHGUI_FilterDlg::onRemoveBtn
740 // Purpose : SLOT. Called then "Remove" button pressed. 
741 //           Removes current string from table
742 //=======================================================================
743 void SMESHGUI_FilterDlg::onRemoveBtn()
744 {
745   Table* aTable = myTables[ getCurrType() ];
746
747   if ( aTable->numRows() == 0 )
748     return;
749
750   QMemArray<int> aRows;
751   for ( int i = 0, n = aTable->numRows(); i < n; i++ )
752   {
753     if ( aTable->isRowSelected( i ) )
754     {
755       aRows.resize( aRows.size() + 1 );
756       aRows[ aRows.size() - 1 ] = i;
757     }
758   }
759
760   aTable->removeRows( aRows );
761
762   // remove control of binary logical operation from last row
763   if ( aTable->numRows() > 0 )
764     aTable->SetEditable( false, aTable->numRows() - 1, 4 );
765
766   updateBtnState();
767 }
768
769 //=======================================================================
770 // name    : SMESHGUI_FilterDlg::onClearBtn
771 // Purpose : SLOT. Called then "Clear" button pressed.
772 //           Removes all strings from table
773 //=======================================================================
774 void SMESHGUI_FilterDlg::onClearBtn()
775 {
776   QTable* aTable = myTables[ getCurrType() ];
777
778   if ( aTable->numRows() == 0 )
779     return;
780
781   while ( aTable->numRows() > 0 )
782     aTable->removeRow( 0 );
783
784   updateBtnState();
785 }
786
787 //=======================================================================
788 // name    : SMESHGUI_FilterDlg::updateBtnState
789 // Purpose : Update button state
790 //=======================================================================
791 void SMESHGUI_FilterDlg::updateBtnState()
792 {
793   myRemoveBtn->setEnabled( myTables[ getCurrType() ]->numRows() > 0 );
794   myClearBtn->setEnabled( myTables[ getCurrType() ]->numRows() > 0 );
795 }
796
797 //=======================================================================
798 // name    : SMESHGUI_FilterDlg::isValid
799 // Purpose : Verify validity of input data
800 //=======================================================================
801 bool SMESHGUI_FilterDlg::isValid() const
802 {
803   Table* aTable = myTables[ getCurrType() ];
804   for ( int i = 0, n = aTable->numRows(); i < n; i++ )
805   {
806     bool isEditable = aTable->IsEditable( i ,2 );
807     bool aRes       = false;
808     int  aThreshold = ( int )aTable->text( i, 2 ).toDouble( &aRes );
809     if ( isEditable && !aRes )
810     {
811       QMessageBox::information( mySMESHGUI->GetDesktop(),
812         tr( "SMESH_INSUFFICIENT_DATA" ), tr( "ERROR" ),
813         QMessageBox::Ok );
814       return false;
815     }
816     else if ( getCurrType() == SMESH::EDGE &&
817               getCriterion( SMESH::EDGE, i ) == MultiBorders &&
818               aThreshold == 1 )
819     {
820       QMessageBox::information( mySMESHGUI->GetDesktop(),
821         tr( "SMESH_INSUFFICIENT_DATA" ), tr( "MULTIEDGES_ERROR" ),
822         QMessageBox::Ok );
823       return false;
824     }
825   }
826
827   return true;
828 }
829
830 //=======================================================================
831 // name    : SMESHGUI_FilterDlg::GetResultIds
832 // Purpose : Get filtered ids
833 //=======================================================================
834 /*void SMESHGUI_FilterDlg::GetResultIds( SMESH::SMESH_Mesh_ptr theMesh,
835                                        QValueList<int>&      theIds ) const
836 {
837   if ( !myPredicate->_is_nil() )
838     theIds = myInputIds;
839   else
840     myPredicate->SetMesh( theMesh );
841   
842   theIds.clear();
843   QValueList<int>::const_iterator anIter;
844   for ( anIter = myInputIds.begin(); anIter != myInputIds.end(); ++anIter )
845     if ( myPredicate->IsSatisfy( *anIter ) )
846      theIds.append( *anIter );
847 }
848 */
849
850 //=======================================================================
851 // name    : SMESHGUI_FilterDlg::SetSourceWg
852 // Purpose : Set widget of parent dialog containing idsto be filtered if
853 //           user select corresponding source radio button
854 //=======================================================================
855 void SMESHGUI_FilterDlg::SetSourceWg( QWidget* theWg )
856 {
857   mySourceWg = theWg;
858 }
859
860 //=======================================================================
861 // name    : SMESHGUI_FilterDlg::SetGroupIds
862 // Purpose : Set mesh
863 //=======================================================================
864 void SMESHGUI_FilterDlg::SetMesh( SMESH::SMESH_Mesh_ptr theMesh )
865 {
866   myMesh = theMesh;
867 }
868
869 //=======================================================================
870 // name    : SMESHGUI_FilterDlg::SetSelection
871 // Purpose : Get filtered ids
872 //=======================================================================
873 void SMESHGUI_FilterDlg::SetSelection( SALOME_Selection* theSel )
874 {
875   mySelection = theSel;
876 }
877
878 //=======================================================================
879 // name    : SMESHGUI_FilterDlg::onApply
880 // Purpose : SLOT called when "Apply" button pressed.
881 //           Assign filters to VTK viewer
882 //=======================================================================
883 bool SMESHGUI_FilterDlg::onApply()
884 {
885   if ( !isValid() )
886     return false;
887
888   try
889   {
890     int aCurrType = getCurrType();
891
892     SMESH::Predicate_ptr aPredicate = createPredicate( aCurrType );
893
894     if ( mySetInViewer->isChecked() )
895       insertFilterInViewer( aPredicate );
896
897     if ( !aPredicate->_is_nil() )
898     {
899       QValueList<int> aResultIds;
900       filterSource( aCurrType, aPredicate, aResultIds );
901       selectInViewer( aCurrType, aResultIds );
902     }
903   }
904   catch( const SALOME::SALOME_Exception& S_ex )
905   {
906     QtCatchCorbaException( S_ex );
907   }
908   catch( ... )
909   {
910   }
911
912   return true;
913 }
914
915 //=======================================================================
916 // name    : SMESHGUI_FilterDlg::createPredicate
917 // Purpose : Create predicate for given type
918 //=======================================================================
919 SMESH::Predicate_ptr SMESHGUI_FilterDlg::createPredicate( const int theType )
920 {
921   SMESH::FilterManager_ptr aFilterMgr = mySMESHGUI->GetFilterMgr();
922   if ( aFilterMgr->_is_nil() )
923     return SMESH::Predicate::_nil();
924
925   QTable* aTable = myTables[ theType ];
926   if ( aTable == 0 )
927     return SMESH::Predicate::_nil();
928
929   // CREATE two lists ( PREDICATES  and LOG OP )
930
931   // Criterion
932   QValueList<SMESH::Predicate_ptr> aPredicates;
933   QValueList<int>                  aLogOps;
934   for ( int i = 0, n = aTable->numRows(); i < n; i++ )
935   {
936     int aCriterion = getCriterion( theType, i );
937
938     SMESH::Predicate_ptr aPredicate = SMESH::Predicate::_nil();
939     SMESH::NumericalFunctor_ptr aFunctor = SMESH::NumericalFunctor::_nil();
940
941     if ( theType == SMESH::EDGE )
942     {
943       switch ( aCriterion )
944       {
945       case FreeBorders:
946         aPredicate = aFilterMgr->CreateFreeBorders();
947         break;
948       case MultiBorders:
949         aFunctor = aFilterMgr->CreateMultiConnection();
950         break;
951       case Length:
952         aFunctor = aFilterMgr->CreateLength();
953         break;
954       default:
955         continue;
956       }
957     }
958     else
959     {
960       switch ( aCriterion )
961       {
962       case AspectRatio:
963         aFunctor = aFilterMgr->CreateAspectRatio();
964         break;
965       case Warping:
966         aFunctor = aFilterMgr->CreateWarping();
967         break;
968       case MinimumAngle:
969         aFunctor = aFilterMgr->CreateMinimumAngle();
970         break;
971       case Taper:
972         aFunctor = aFilterMgr->CreateTaper();
973         break;
974       case Skew:
975         aFunctor = aFilterMgr->CreateSkew();
976         break;
977       case Area:
978         aFunctor = aFilterMgr->CreateArea();
979         break;
980       default:
981         continue;
982       }
983     }
984
985     // Comparator
986     if ( !aFunctor->_is_nil() && aPredicate->_is_nil() )
987     {
988       QComboTableItem* aCombo = (QComboTableItem*)aTable->item( i, 1 );
989       int aCompareOp = aCombo->currentItem();
990       double aThreshold = aTable->text( i, 2 ).toDouble();
991
992       SMESH::Comparator_ptr aComparator = SMESH::Comparator::_nil();
993
994       if ( aCompareOp == LessThan )
995         aComparator = aFilterMgr->CreateLessThan();
996       else if ( aCompareOp == MoreThan )
997         aComparator = aFilterMgr->CreateMoreThan();
998       else if ( aCompareOp == EqualTo )
999         aComparator = aFilterMgr->CreateEqualTo();
1000       else
1001         continue;
1002
1003       aComparator->SetNumFunctor( aFunctor );
1004       aComparator->SetMargin( aThreshold );
1005
1006       aPredicate = aComparator;
1007     }
1008
1009     // Logical not
1010     QCheckTableItem* anItem = (QCheckTableItem*)aTable->item( i, 3 );
1011     if ( anItem->isChecked() )
1012     {
1013       SMESH::LogicalNOT_ptr aNotPred = aFilterMgr->CreateLogicalNOT();
1014       aNotPred->SetPredicate( aPredicate );
1015       aPredicate = aNotPred;
1016     }
1017
1018     // logical op
1019     int aLogOp = ( i == n - 1 ) ? LO_Undefined
1020                                 : ( (QComboTableItem*)aTable->item( i, 4 ) )->currentItem();
1021     aPredicates.append( aPredicate );
1022     aLogOps.append( aLogOp );
1023
1024   } // for
1025
1026   // CREATE ONE PREDICATE FROM PREVIOUSLY CREATED MAP
1027
1028   // combine all "AND" operations
1029
1030   QValueList<SMESH::Predicate_ptr> aResList;
1031
1032   QValueList<SMESH::Predicate_ptr>::iterator aPredIter;
1033   QValueList<int>::iterator                  aLogOpIter;
1034
1035   SMESH::Predicate_ptr aPrevPredicate = SMESH::Predicate::_nil();
1036   int aPrevLogOp = LO_Undefined;
1037
1038   for ( aPredIter = aPredicates.begin(), aLogOpIter = aLogOps.begin();
1039         aPredIter != aPredicates.end() && aLogOpIter != aLogOps.end();
1040         ++aPredIter, ++aLogOpIter )
1041   {
1042     int aCurrLogOp = *aLogOpIter;
1043
1044     SMESH::Predicate_ptr aCurrPred = SMESH::Predicate::_nil();
1045
1046     if ( aPrevLogOp == LO_And )
1047     {
1048
1049       SMESH::LogicalBinary_ptr aBinaryPred = aFilterMgr->CreateLogicalAND();
1050       aBinaryPred->SetPredicate1( aPrevPredicate );
1051       aBinaryPred->SetPredicate2( *aPredIter );
1052       aCurrPred = aBinaryPred;
1053     }
1054     else
1055       aCurrPred = *aPredIter;
1056
1057     if ( aCurrLogOp != LO_And )
1058       aResList.append( aCurrPred );
1059
1060     aPrevPredicate = aCurrPred;
1061     aPrevLogOp = aCurrLogOp;
1062   }
1063
1064   // combine all "OR" operations
1065
1066   SMESH::Predicate_ptr aResPredicate = SMESH::Predicate::_nil();
1067
1068   if ( aResList.count() == 1 )
1069     aResPredicate = aResList.first();
1070   else if ( aResList.count() > 1 )
1071   {
1072     QValueList<SMESH::Predicate_ptr>::iterator anIter = aResList.begin();
1073     aResPredicate = *anIter;
1074     anIter++;
1075     for ( ; anIter != aResList.end(); ++anIter )
1076     {
1077       SMESH::LogicalBinary_ptr aBinaryPred = aFilterMgr->CreateLogicalOR();
1078       aBinaryPred->SetPredicate1( aResPredicate );
1079       aBinaryPred->SetPredicate2( *anIter );
1080       aResPredicate = aBinaryPred;
1081     }
1082   }
1083
1084   return aResPredicate;
1085 }
1086
1087 //=======================================================================
1088 // name    : SMESHGUI_FilterDlg::insertFilterInViewer
1089 // Purpose : Insert filter in viewer
1090 //=======================================================================
1091 void SMESHGUI_FilterDlg::insertFilterInViewer( SMESH::Predicate_ptr thePred )
1092 {
1093   VTKViewer_InteractorStyleSALOME* aStyle = ((VTKViewer_ViewFrame*)mySMESHGUI->GetActiveStudy()->
1094     getActiveStudyFrame()->getRightFrame()->getViewFrame())->
1095       getRWInteractor()->GetInteractorStyleSALOME();
1096
1097   if ( thePred->_is_nil() )
1098   {
1099     if ( myType == SMESH::EDGE )
1100       aStyle->RemoveEdgeFilter();
1101     else if ( myType == SMESH::FACE )
1102       aStyle->RemoveFaceFilter();
1103   }
1104   else
1105   {
1106     Handle(SMESHGUI_Filter) aFilter = new SMESHGUI_Filter();
1107     aFilter->SetPredicate( thePred );
1108     if ( myType == SMESH::EDGE )
1109       aStyle->SetEdgeFilter( aFilter );
1110     else if ( myType == SMESH::FACE )
1111       aStyle->SetFaceFilter( aFilter );
1112   }
1113 }
1114
1115 //=======================================================================
1116 // name    : SMESHGUI_FilterDlg::filterSource
1117 // Purpose : Filter source ids
1118 //=======================================================================
1119 void SMESHGUI_FilterDlg::filterSource( const int theType,
1120                                        SMESH::Predicate_ptr thePred,
1121                                        QValueList<int>& theResIds )
1122 {
1123   theResIds.clear();
1124   
1125   int aSourceId = mySourceGrp->id( mySourceGrp->selected() );
1126
1127   if ( aSourceId == Mesh )
1128   {
1129     if ( myMesh->_is_nil() )
1130       return;
1131     SMESH::FilterManager_ptr aFilterMgr = mySMESHGUI->GetFilterMgr();
1132     SMESH::Filter_var aFilter = aFilterMgr->CreateFilter();
1133     aFilter->SetPredicate( thePred );
1134     SMESH::long_array_var anIds = aFilter->GetElementsId( myMesh );
1135     for ( int i = 0, n = anIds->length(); i < n; i++ )
1136       theResIds.append( anIds[ i ] );
1137   }
1138   else if ( aSourceId == Selection )
1139   {
1140     filterSelectionSource( theType, thePred, theResIds );
1141   }
1142   else if ( aSourceId == Dialog )
1143   {
1144     // retrieve ids from dialog
1145     QValueList<int> aDialogIds;
1146     getIdsFromWg( mySourceWg, aDialogIds );
1147     
1148     if ( myMesh->_is_nil() )
1149     {
1150       theResIds = aDialogIds;
1151       return;
1152     }
1153
1154     // filter ids
1155     thePred->SetMesh( myMesh );
1156     QValueList<int>::const_iterator anIter;
1157     for ( anIter = aDialogIds.begin(); anIter != aDialogIds.end(); ++ anIter )
1158       if ( thePred->IsSatisfy( *anIter ) )
1159         theResIds.append( *anIter );
1160
1161     // set ids to the dialog
1162     setIdsToWg( mySourceWg, theResIds );
1163   }
1164 }
1165
1166 //=======================================================================
1167 // name    : SMESHGUI_FilterDlg::filterSelectionSource
1168 // Purpose : Filter source selection
1169 //=======================================================================
1170 void SMESHGUI_FilterDlg::filterSelectionSource( const int theType,
1171                                                 SMESH::Predicate_ptr thePred,
1172                                                 QValueList<int>& theResIds )
1173 {
1174   theResIds.clear();
1175   if ( myMesh->_is_nil() || mySelection == 0 )
1176     return;
1177
1178   // Create map of entities to be filtered
1179   TColStd_MapOfInteger aToBeFiltered;
1180   Standard_Boolean aRes = false;
1181   SALOME_ListIteratorOfListIO anIter( mySelection->StoredIObjects() );
1182   
1183   for ( ; anIter.More(); anIter.Next() )
1184   {
1185     // process sub mesh
1186     SMESH::SMESH_subMesh_ptr aSubMesh = mySMESHGUI->ConvertIOinSubMesh( anIter.Value(), aRes );
1187     if ( aRes && !aSubMesh->_is_nil() )
1188     {
1189       if ( aSubMesh->GetFather()->GetId() == myMesh->GetId() )
1190       {
1191         SMESH::long_array_var anIds =
1192           theType == SMESH::NODE ? aSubMesh->GetNodesId() : aSubMesh->GetElementsId();
1193         for ( int i = 0, n = anIds->length(); i < n; i++ )
1194           aToBeFiltered.Add( anIds[ i ] );
1195       }
1196     }
1197
1198     // process group
1199     SMESH::SMESH_Group_ptr aGroup = mySMESHGUI->ConvertIOinSMESHGroup( anIter.Value(), aRes );
1200     if ( aRes && !aGroup->_is_nil() )
1201     {
1202       if ( aGroup->GetType() == theType && aGroup->GetMesh()->GetId() == myMesh->GetId() )
1203       {
1204         SMESH::long_array_var anIds = aGroup->GetListOfID();
1205         for ( int i = 0, n = anIds->length(); i < n; i++ )
1206           aToBeFiltered.Add( anIds[ i ] );
1207       }
1208     }
1209
1210     // process mesh
1211     SMESH::SMESH_Mesh_ptr aMeshPtr = mySMESHGUI->ConvertIOinMesh( anIter.Value(), aRes );
1212     if ( aRes && !aMeshPtr->_is_nil() && aMeshPtr->GetId() == myMesh->GetId() )
1213     {
1214       TColStd_MapOfInteger aVtkMap;
1215       mySelection->GetIndex( anIter.Value(), aVtkMap );
1216
1217       if ( aVtkMap.Extent() > 0 )
1218       {
1219         SMESH_Actor *anActor = mySMESHGUI->FindActorByEntry(
1220           anIter.Value()->getEntry(), aRes, true );
1221         if ( aRes && anActor != 0 )
1222         {
1223           TColStd_MapIteratorOfMapOfInteger aVtkMapIter( aVtkMap );
1224           for ( ; aVtkMapIter.More(); aVtkMapIter.Next() )
1225             aToBeFiltered.Add( theType == SMESH::NODE
1226               ? anActor->GetNodeObjId( aVtkMapIter.Key() )
1227               : anActor->GetElemObjId( aVtkMapIter.Key() ) );
1228         }
1229       }
1230     }
1231   }
1232
1233   // Filter entities
1234   thePred->SetMesh( myMesh );
1235   TColStd_MapIteratorOfMapOfInteger aResIter( aToBeFiltered );
1236   for ( ; aResIter.More(); aResIter.Next() )
1237     if ( thePred->IsSatisfy( aResIter.Key() ) )
1238       theResIds.append( aResIter.Key() );
1239 }
1240
1241 //=======================================================================
1242 // name    : SMESHGUI_FilterDlg::selectInViewer
1243 // Purpose : Select given entities in viewer
1244 //=======================================================================
1245 void SMESHGUI_FilterDlg::selectInViewer( const int theType, const QValueList<int>& theIds )
1246 {
1247   if ( mySelection == 0 || myMesh->_is_nil() )
1248     return;
1249
1250   // Set new selection mode if necessary
1251   Selection_Mode aSelMode = getSelMode( theType );
1252   if ( aSelMode != mySelection->SelectionMode() )
1253   {
1254     mySelection->ClearIObjects();
1255     mySelection->ClearFilters();
1256     if ( aSelMode == NodeSelection )
1257       mySMESHGUI->ViewNodes();
1258     QAD_Application::getDesktop()->SetSelectionMode( aSelMode );
1259   }
1260
1261   Standard_Boolean aRes = false;
1262   SMESH_Actor* anActor = mySMESHGUI->FindActor( myMesh, aRes, true );
1263   if ( !aRes || anActor == 0 || !anActor->hasIO() )
1264     return;
1265
1266   Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
1267   mySelection->ClearIObjects();
1268   mySelection->AddIObject( anIO, false );
1269
1270   TColStd_MapOfInteger aMap;
1271   QValueList<int>::const_iterator anIter;
1272   for ( anIter = theIds.begin(); anIter != theIds.end(); ++anIter )
1273   {
1274     std::vector<int> aVtkList = anActor->GetElemVtkId( *anIter );
1275     std::vector<int>::iterator it;
1276     for ( it = aVtkList.begin(); it != aVtkList.end(); ++it )
1277       aMap.Add( *it );
1278   }
1279
1280   mySelection->AddOrRemoveIndex( anIO, aMap, false, true );
1281   
1282 }
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302