Salome HOME
1bb4e6184b43cd2a6080593a1cd7261ef0b592d6
[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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File   : SMESHGUI_FilterDlg.cxx
23 // Author : Sergey LITONIN, Open CASCADE S.A.S.
24 //
25
26 // SMESH includes
27 #include "SMESHGUI_FilterDlg.h"
28
29 #include "SMESHGUI.h"
30 #include "SMESHGUI_Utils.h"
31 #include "SMESHGUI_VTKUtils.h"
32 #include "SMESHGUI_Filter.h"
33 #include "SMESHGUI_FilterUtils.h"
34 #include "SMESHGUI_FilterLibraryDlg.h"
35
36 #include <SMESH_Actor.h>
37 #include <SMESH_NumberFilter.hxx>
38 #include <SMESH_TypeFilter.hxx>
39
40 // SALOME GEOM includes
41 #include <GEOMBase.h>
42 #include <GEOM_FaceFilter.h>
43 #include <GEOM_TypeFilter.h>
44
45 // SALOME GUI includes
46 #include <SUIT_Desktop.h>
47 #include <SUIT_ResourceMgr.h>
48 #include <SUIT_Session.h>
49 #include <SUIT_MessageBox.h>
50
51 #include <LightApp_Application.h>
52 #include <LightApp_SelectionMgr.h>
53 #include <SalomeApp_Tools.h>
54 #include <SalomeApp_Study.h>
55
56 #include <SALOME_ListIO.hxx>
57 #include <SALOME_ListIteratorOfListIO.hxx>
58 #include <SALOME_DataMapIteratorOfDataMapOfIOMapOfInteger.hxx>
59
60 #include <SVTK_ViewWindow.h>
61
62 // SALOME KERNEL includes
63 #include <SALOMEDSClient_Study.hxx>
64
65 // OCCT includes
66 #include <StdSelect_TypeOfFace.hxx>
67 #include <BRep_Tool.hxx>
68 #include <TopoDS.hxx>
69 #include <TopoDS_Shape.hxx>
70 #include <Geom_Plane.hxx>
71 #include <Geom_CylindricalSurface.hxx>
72 #include <Precision.hxx>
73 #include <TColStd_MapOfInteger.hxx>
74 #include <TColStd_IndexedMapOfInteger.hxx>
75 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
76
77 // Qt includes
78 #include <QFrame>
79 #include <QLineEdit>
80 #include <QPushButton>
81 #include <QGroupBox>
82 #include <QTableWidget>
83 #include <QStringList>
84 #include <QHBoxLayout>
85 #include <QVBoxLayout>
86 #include <QGridLayout>
87 #include <QStackedWidget>
88 #include <QApplication>
89 #include <QComboBox>
90 #include <QFontMetrics>
91 #include <QLabel>
92 #include <QButtonGroup>
93 #include <QRadioButton>
94 #include <QRegExp>
95 #include <QListWidget>
96 #include <QCheckBox>
97 #include <QItemDelegate>
98 #include <QDoubleValidator>
99 #include <QKeyEvent>
100 #include <QHeaderView>
101
102 // IDL includes
103 #include <SALOMEconfig.h>
104 #include CORBA_SERVER_HEADER(SMESH_Group)
105
106 #define SPACING 6
107 #define MARGIN  11
108
109 //---------------------------------------
110 // maxLength
111 //---------------------------------------
112 static int maxLength (const QMap<int, QString> theMap, const QFontMetrics& theMetrics)
113 {
114   int aRes = 0;
115   QMap<int, QString>::const_iterator anIter;
116   for (anIter = theMap.begin(); anIter != theMap.end(); ++anIter)
117     aRes = qMax(aRes, theMetrics.width(anIter.value()));
118   return aRes;
119 }
120
121 //---------------------------------------
122 // getFilterId
123 //---------------------------------------
124 static int getFilterId (SMESH::ElementType theType)
125 {
126   switch (theType)
127   {
128     case SMESH::NODE   : return SMESH::NodeFilter;
129     case SMESH::EDGE   : return SMESH::EdgeFilter;
130     case SMESH::FACE   : return SMESH::FaceFilter;
131     case SMESH::VOLUME : return SMESH::VolumeFilter;
132     case SMESH::ALL    : return SMESH::AllElementsFilter;
133     default            : return SMESH::UnknownFilter;
134   }
135 }
136
137 /*
138   Class       : SMESHGUI_FilterTable::AdditionalWidget
139   Description : Class for storing additional parameters of criterion
140 */
141
142 class SMESHGUI_FilterTable::AdditionalWidget : public QWidget
143 {
144 public:
145   enum { Tolerance };
146
147 public:
148   AdditionalWidget(QWidget* theParent);
149   virtual ~AdditionalWidget();
150
151   virtual QList<int>      GetParameters() const;
152   virtual bool            IsValid(const bool = true) const;
153   virtual double          GetDouble(const int) const;
154   virtual int             GetInteger(const int) const;
155   virtual QString         GetString(const int) const;
156   virtual void            SetDouble(const int, const double);
157   virtual void            SetInteger(const int, const int);
158   virtual void            SetString(const int, const QString&);
159   void                    SetEditable(const int, const bool);
160   void                    SetEditable(const bool);
161
162 private:
163   QMap< int, QLineEdit* > myLineEdits;
164 };
165
166 SMESHGUI_FilterTable::AdditionalWidget::AdditionalWidget (QWidget* theParent)
167   : QWidget(theParent)
168 {
169   QLabel* aLabel = new QLabel(tr("SMESH_TOLERANCE"), this);
170   myLineEdits[ Tolerance ] = new QLineEdit(this);
171   QDoubleValidator* aValidator = new QDoubleValidator(myLineEdits[ Tolerance ]);
172   aValidator->setBottom(0);
173   myLineEdits[ Tolerance ]->setValidator(aValidator);
174
175   QHBoxLayout* aLay = new QHBoxLayout(this);
176   aLay->setSpacing(SPACING);
177   aLay->setMargin(0);
178
179   aLay->addWidget(aLabel);
180   aLay->addWidget(myLineEdits[ Tolerance ]);
181   aLay->addStretch();
182
183   QString aText = QString("%1").arg(Precision::Confusion());
184   myLineEdits[ Tolerance ]->setText(aText);
185 }
186
187 SMESHGUI_FilterTable::AdditionalWidget::~AdditionalWidget()
188 {
189 }
190
191 QList<int> SMESHGUI_FilterTable::AdditionalWidget::GetParameters() const
192 {
193   QList<int> theList;
194   theList.append(Tolerance);
195   return theList;
196 }
197
198 bool SMESHGUI_FilterTable::AdditionalWidget::IsValid (const bool theMsg) const
199 {
200   if (!isEnabled())
201     return true;
202
203   QList<int> aParams = GetParameters();
204   QList<int>::const_iterator anIter;
205   for (anIter = aParams.begin(); anIter != aParams.end(); ++anIter) {
206     const QLineEdit* aWg = myLineEdits[ *anIter ];
207     int p = 0;
208     QString aText = aWg->text();
209     if (aWg->isEnabled() && aWg->validator()->validate(aText, p) != QValidator::Acceptable) {
210       if (theMsg)
211         SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"),
212                                      tr("SMESHGUI_INVALID_PARAMETERS"));
213       return false;
214     }
215   }
216
217   return true;
218 }
219
220 double SMESHGUI_FilterTable::AdditionalWidget::GetDouble (const int theId) const
221 {
222   return myLineEdits.contains(theId) ? myLineEdits[ theId ]->text().toDouble() : 0;
223 }
224
225 int SMESHGUI_FilterTable::AdditionalWidget::GetInteger (const int theId) const
226 {
227   return myLineEdits.contains(theId) ? myLineEdits[ theId ]->text().toInt() : 0;
228 }
229
230 QString SMESHGUI_FilterTable::AdditionalWidget::GetString (const int theId) const
231 {
232   return myLineEdits.contains(theId) ? myLineEdits[ theId ]->text() : QString("");
233 }
234
235 void SMESHGUI_FilterTable::AdditionalWidget::SetDouble (const int theId, const double theVal)
236 {
237   if (myLineEdits.contains(theId))
238     myLineEdits[ theId ]->setText(QString("%1").arg(theVal));
239 }
240
241 void SMESHGUI_FilterTable::AdditionalWidget::SetInteger (const int theId, const int theVal)
242 {
243   if (myLineEdits.contains(theId))
244     myLineEdits[ theId ]->setText(QString("%1").arg(theVal));
245 }
246
247 void SMESHGUI_FilterTable::AdditionalWidget::SetString (const int theId, const QString& theVal)
248 {
249   if (myLineEdits.contains(theId))
250     myLineEdits[ theId ]->setText(theVal);
251 }
252
253 void SMESHGUI_FilterTable::AdditionalWidget::SetEditable (const int theId, const bool isEditable)
254 {
255   if (myLineEdits.contains(theId))
256     myLineEdits[ theId ]->setReadOnly(!isEditable);
257 }
258
259 void SMESHGUI_FilterTable::AdditionalWidget::SetEditable (const bool isEditable)
260 {
261   QList<int> aParams = GetParameters();
262   QList<int>::const_iterator anIter;
263   for (anIter = aParams.begin(); anIter != aParams.end(); ++anIter)
264     SetEditable( *anIter,  isEditable );
265 }
266
267 /*
268   Class       : SMESHGUI_FilterTable::ComboItem
269   Description : Combo table item. Identificator corresponding to string may be assigned
270 */
271
272 class SMESHGUI_FilterTable::ComboItem : public QTableWidgetItem
273 {
274 public:
275   static int     Type();
276
277   ComboItem( const QMap<int, QString>& );
278
279   void           setItems( const QMap<int, QString>& );
280   void           clear();
281   int            count() const;
282
283   int            value() const;
284   void           setValue( const int );
285
286 private:
287   int            id( int ) const;
288   int            index( int ) const;
289
290 private:
291   QMap<int, int> myIdToIdx;
292 };
293
294 int SMESHGUI_FilterTable::ComboItem::Type()
295 {
296   return QTableWidgetItem::UserType + 1;
297 }
298
299 SMESHGUI_FilterTable::ComboItem::ComboItem( const QMap<int, QString>& theIds )
300  : QTableWidgetItem( Type() )
301 {
302   setItems( theIds );
303 }
304
305 void SMESHGUI_FilterTable::ComboItem::setItems( const QMap<int, QString>& theIds )
306 {
307   myIdToIdx.clear();
308   QMap<int, QString>::const_iterator it;
309   QStringList items;
310   for ( it = theIds.begin(); it != theIds.end(); ++it ) {
311     myIdToIdx[it.key()] = items.count();
312     items.append( it.value() );
313   }
314   setData( Qt::UserRole, items );
315   setValue( id( 0 ) ); 
316 }
317
318 void SMESHGUI_FilterTable::ComboItem::clear()
319 {
320   QMap<int, QString> empty;
321   setItems( empty );
322 }
323
324 int SMESHGUI_FilterTable::ComboItem::count() const
325 {
326   return myIdToIdx.count();
327 }
328
329 int SMESHGUI_FilterTable::ComboItem::value() const
330 {
331   return( id( data( Qt::UserRole ).toStringList().indexOf( text() ) ) ); 
332 }
333
334 void SMESHGUI_FilterTable::ComboItem::setValue( const int theId )
335 {
336   int idx = index( theId );
337   QStringList items = data( Qt::UserRole ).toStringList();
338   setText( idx >= 0 && idx < items.count() ? items[idx] : "" );
339 }
340
341 int SMESHGUI_FilterTable::ComboItem::id( int idx ) const
342 {
343   QMap<int,int>::const_iterator it;
344   for ( it = myIdToIdx.begin(); it != myIdToIdx.end(); ++it )
345     if ( it.value() == idx ) return it.key();
346   return -1;
347 }
348
349 int SMESHGUI_FilterTable::ComboItem::index( int i ) const
350 {
351   return myIdToIdx.contains( i ) ? myIdToIdx[i] : -1;
352 }
353 /*
354   Class       : SMESHGUI_FilterTable::CheckItem
355   Description : Check table item.
356 */
357
358 class SMESHGUI_FilterTable::CheckItem : public QTableWidgetItem
359 {
360 public:
361   static int     Type();
362
363   CheckItem( bool = false );
364   CheckItem( const QString&, bool = false );
365   ~CheckItem();
366
367   void  setChecked( bool );
368   bool  checked() const;
369 };
370
371 int SMESHGUI_FilterTable::CheckItem::Type()
372 {
373   return QTableWidgetItem::UserType + 2;
374 }
375
376 SMESHGUI_FilterTable::CheckItem::CheckItem( bool value )
377  : QTableWidgetItem( Type() )
378 {
379   Qt::ItemFlags f = flags();
380   f = f | Qt::ItemIsUserCheckable;
381   f = f & ~Qt::ItemIsTristate;
382   f = f & ~Qt::ItemIsEditable;
383   setFlags( f );
384   setChecked(value);
385 }
386
387 SMESHGUI_FilterTable::CheckItem::CheckItem( const QString& text, bool value )
388  : QTableWidgetItem( Type() )
389 {
390   Qt::ItemFlags f = flags();
391   f = f | Qt::ItemIsUserCheckable;
392   f = f & ~Qt::ItemIsTristate;
393   f = f & ~Qt::ItemIsEditable;
394   setFlags( f );
395   setChecked( value );
396   setText( text );
397 }
398
399 SMESHGUI_FilterTable::CheckItem::~CheckItem()
400 {
401 }
402
403 void SMESHGUI_FilterTable::CheckItem::setChecked( bool value )
404 {
405   setCheckState( value ? Qt::Checked : Qt::Unchecked );
406 }
407
408 bool SMESHGUI_FilterTable::CheckItem::checked() const
409 {
410   return checkState() == Qt::Checked;
411 }
412
413 /*
414   Class       : SMESHGUI_FilterTable::ComboDelegate
415   Description : Table used by this widget
416 */
417
418 class SMESHGUI_FilterTable::ComboDelegate : public QItemDelegate
419 {
420 public:
421   ComboDelegate( QObject* = 0 );
422   ~ComboDelegate();
423   
424   QWidget*      createEditor( QWidget*, const QStyleOptionViewItem&,
425                               const QModelIndex& ) const;
426   
427   void          setEditorData( QWidget*, const QModelIndex& ) const;
428   void          setModelData( QWidget*, QAbstractItemModel*, const QModelIndex& ) const;
429   
430   void          updateEditorGeometry( QWidget*, const QStyleOptionViewItem&, 
431                                       const QModelIndex& ) const;
432 private:
433   QTableWidget* myTable;
434 };
435
436 SMESHGUI_FilterTable::ComboDelegate::ComboDelegate( QObject* parent )
437   : QItemDelegate( parent ), 
438     myTable( qobject_cast<QTableWidget*>( parent ) )
439 {
440 }
441   
442 SMESHGUI_FilterTable::ComboDelegate::~ComboDelegate()
443 {
444 }
445
446 QWidget* SMESHGUI_FilterTable::ComboDelegate::createEditor( QWidget* parent,
447                                                             const QStyleOptionViewItem& option,
448                                                             const QModelIndex& index ) const
449 {
450   QStringList l = index.data( Qt::UserRole ).toStringList();
451   if ( !l.isEmpty() ) {
452     QComboBox* cb = new QComboBox( parent );
453     cb->setFrame( false );
454     cb->addItems( l );
455     return cb;
456   }
457   return QItemDelegate::createEditor( parent, option, index );
458 }
459
460 void SMESHGUI_FilterTable::ComboDelegate::setEditorData( QWidget* editor, 
461                                                          const QModelIndex& index ) const
462 {
463   QString value = index.model()->data( index, Qt::DisplayRole ).toString();
464   QComboBox* cb = dynamic_cast<QComboBox*>( editor );
465   bool bOk = false;
466   if ( cb ) {
467     int i = cb->findText( value );
468     if ( i >= 0 ) {
469       cb->setCurrentIndex( i );
470       bOk = true;
471     }
472   }
473   if ( !bOk ) QItemDelegate::setEditorData( editor, index );
474 }
475
476 void SMESHGUI_FilterTable::ComboDelegate::setModelData( QWidget* editor,
477                                                         QAbstractItemModel* model,
478                                                         const QModelIndex& index) const
479 {
480   QComboBox* cb = dynamic_cast<QComboBox*>( editor );
481   if ( cb ) model->setData( index, cb->currentText(), Qt::DisplayRole );
482   else QItemDelegate::setModelData( editor, model, index );
483 }
484
485 void SMESHGUI_FilterTable::ComboDelegate::updateEditorGeometry( QWidget* editor,
486                                                                 const QStyleOptionViewItem& option, 
487                                                                 const QModelIndex& index ) const
488 {
489   editor->setGeometry( option.rect );
490 }
491
492 /*
493   Class       : SMESHGUI_FilterTable::Table
494   Description : Table used by this widget
495 */
496
497 class SMESHGUI_FilterTable::Table : public QTableWidget
498 {
499 public:
500   Table( QWidget* = 0 );
501   Table( int, int, QWidget* = 0 );
502   virtual ~Table();
503
504   void                    setEditable( bool, int, int );
505   bool                    isEditable( int, int ) const;
506
507   void                    setReadOnly( bool );
508   bool                    isReadOnly() const;
509
510   void                    insertRows( int, int = 1 );
511   QString                 text( int, int );
512
513   QList<int>              selectedRows();
514 };
515
516 //=======================================================================
517 // name    : SMESHGUI_FilterTable::Table::Table
518 // Purpose : Constructor
519 //=======================================================================
520 SMESHGUI_FilterTable::Table::Table (QWidget* parent)
521 : QTableWidget(parent)
522 {
523   // set custom item delegate
524   setItemDelegate( new ComboDelegate(this) );
525   // set edit triggers by default
526   setReadOnly( false );
527 }
528
529 SMESHGUI_FilterTable::Table::Table (int numRows, int numCols, QWidget* parent)
530 : QTableWidget(numRows, numCols, parent)
531 {
532   // set custom item delegate
533   setItemDelegate( new ComboDelegate(this) );
534   // set edit triggers by default
535   setReadOnly( false );
536 }
537
538 SMESHGUI_FilterTable::Table::~Table()
539 {
540 }
541
542 //=======================================================================
543 // name    : SMESHGUI_FilterTable::Table::setEditable
544 // Purpose : Set editable of specified cell
545 //=======================================================================
546 void SMESHGUI_FilterTable::Table::setEditable (bool isEditable,
547                                                int row, int col)
548 {
549   QTableWidgetItem* anItem = item( row, col );
550   if ( anItem ) {
551     Qt::ItemFlags f = anItem->flags();
552     if ( !isEditable ) f = f & ~Qt::ItemIsEditable;
553     else f = f | Qt::ItemIsEditable;
554     anItem->setFlags( f );
555   }
556 }
557
558 //=======================================================================
559 // name    : SMESHGUI_FilterTable::Table::isEditable
560 // Purpose : Verify wheter cell is editable
561 //=======================================================================
562 bool SMESHGUI_FilterTable::Table::isEditable (int row, int col) const
563 {
564   QTableWidgetItem* anItem = item( row, col );
565   return anItem == 0 || anItem->flags() & Qt::ItemIsEditable;
566 }
567
568 void SMESHGUI_FilterTable::Table::setReadOnly( bool on )
569 {
570   setEditTriggers( on ? 
571                    QAbstractItemView::NoEditTriggers  :
572                    QAbstractItemView::DoubleClicked   |
573                    QAbstractItemView::SelectedClicked |
574                    QAbstractItemView::EditKeyPressed  |
575                    QAbstractItemView::AnyKeyPressed );
576 }
577
578 bool SMESHGUI_FilterTable::Table::isReadOnly() const
579 {
580   return editTriggers() != QAbstractItemView::NoEditTriggers;
581 }
582
583 //=======================================================================
584 // name    : SMESHGUI_FilterTable::Table::insertRows
585 // Purpose : Insert rows (virtual redefined)
586 //=======================================================================
587 void SMESHGUI_FilterTable::Table::insertRows (int row, int count)
588 {
589   closePersistentEditor( currentItem() );
590   while ( count-- ) insertRow( row );
591 }
592
593 //=======================================================================
594 // name    : SMESHGUI_FilterTable::Table::text
595 // Purpose : Get text from cell (virtual redefined)
596 //=======================================================================
597 QString SMESHGUI_FilterTable::Table::text (int row, int col)
598 {
599   closePersistentEditor( currentItem() );
600   QTableWidgetItem* anItem = item( row, col );
601   return anItem ? anItem->text() : QString();
602 }
603
604 QList<int> SMESHGUI_FilterTable::Table::selectedRows()
605 {
606   QList<QTableWidgetItem*> selItems = selectedItems();
607   QTableWidgetItem* anItem;
608   QList<int> rows;
609
610   foreach( anItem, selItems ) {
611     int r = row( anItem );
612     if ( !rows.contains( r ) ) rows.append( r );
613   }
614
615   qSort( rows );
616   return rows;
617 }
618
619 /*
620   Class       : SMESHGUI_FilterTable
621   Description : Frame containig
622                   - Button group for switching entity type
623                   - Table for displaying filter criterions
624                   - Buttons for editing table and filter libraries
625 */
626
627 //=======================================================================
628 // name    : SMESHGUI_FilterTable::SMESHGUI_FilterTable
629 // Purpose : Constructor
630 //=======================================================================
631 SMESHGUI_FilterTable::SMESHGUI_FilterTable( SMESHGUI* theModule,
632                                             QWidget* parent,
633                                             const int type )
634 : QWidget( parent ),
635   myIsLocked( false ),
636   mySMESHGUI( theModule )
637 {
638   myEntityType = -1;
639
640   QList<int> aTypes;
641   aTypes.append(type);
642   Init(aTypes);
643 }
644
645 //=======================================================================
646 // name    : SMESHGUI_FilterTable::SMESHGUI_FilterTable
647 // Purpose : Constructor
648 //=======================================================================
649 SMESHGUI_FilterTable::SMESHGUI_FilterTable( SMESHGUI* theModule,
650                                             QWidget* parent,
651                                             const QList<int>& types )
652 : QWidget( parent ),
653   myIsLocked( false ),
654   mySMESHGUI( theModule )
655 {
656   myEntityType = -1;
657   Init(types);
658 }
659
660 SMESHGUI_FilterTable::~SMESHGUI_FilterTable()
661 {
662 }
663
664 //=======================================================================
665 // name    : SMESHGUI_FilterTable::Init
666 // Purpose : Create table corresponding to the specified type
667 //=======================================================================
668 void SMESHGUI_FilterTable::Init (const QList<int>& theTypes)
669 {
670   if (theTypes.isEmpty())
671     return;
672
673   // Create buttons if necessary
674
675   if (myTables.isEmpty())
676   {
677     int aType = theTypes.first();
678
679     // create main layout
680     QVBoxLayout* aMainLay = new QVBoxLayout(this);
681     aMainLay->setMargin( 0 );
682     aMainLay->setSpacing( SPACING );
683
684     // create switch of entity types
685     myEntityTypeBox = new QGroupBox(tr("ENTITY_TYPE"), this);
686     QHBoxLayout* myEntityTypeBoxLayout = new QHBoxLayout(myEntityTypeBox);
687     myEntityTypeBoxLayout->setMargin( MARGIN );
688     myEntityTypeBoxLayout->setSpacing( SPACING );
689     myEntityTypeGrp = new QButtonGroup(this);
690
691     const QMap<int, QString>& aSupportedTypes = getSupportedTypes();
692     QMap<int, QString>::const_iterator anIter;
693     for (anIter = aSupportedTypes.begin(); anIter != aSupportedTypes.end(); ++anIter)
694     {
695       QRadioButton* aBtn = new QRadioButton(anIter.value(), myEntityTypeBox);
696       myEntityTypeGrp->addButton(aBtn, anIter.key());
697       myEntityTypeBoxLayout->addWidget(aBtn);
698     }
699
700     myTableGrp = new QGroupBox(tr("FILTER"), this );
701
702     // create table
703     mySwitchTableGrp = new QWidget(myTableGrp);
704     QVBoxLayout* mySwitchTableGrpLayout = new QVBoxLayout(mySwitchTableGrp);
705     mySwitchTableGrpLayout->setMargin(0);
706     mySwitchTableGrpLayout->setSpacing(0);
707
708     myTables[ aType ] = createTable(mySwitchTableGrp, aType);
709     mySwitchTableGrpLayout->addWidget(myTables[ aType ]);
710
711     // create buttons
712     myAddBtn      = new QPushButton(tr("ADD"),       myTableGrp);
713     myRemoveBtn   = new QPushButton(tr("REMOVE"),    myTableGrp);
714     myClearBtn    = new QPushButton(tr("CLEAR"),     myTableGrp);
715     myInsertBtn   = new QPushButton(tr("INSERT"),    myTableGrp);
716     myCopyFromBtn = new QPushButton(tr("COPY_FROM"), myTableGrp);
717     myAddToBtn    = new QPushButton(tr("ADD_TO"),    myTableGrp);
718
719     myAddBtn->setAutoDefault(false);
720     myRemoveBtn->setAutoDefault(false);
721     myClearBtn->setAutoDefault(false);
722     myInsertBtn->setAutoDefault(false);
723     myCopyFromBtn->setAutoDefault(false);
724     myAddToBtn->setAutoDefault(false);
725
726     myCopyFromBtn->hide();
727     myAddToBtn->hide();
728
729     // layout widgets
730     QGridLayout* aLay = new QGridLayout(myTableGrp);
731     aLay->setMargin(0);
732     aLay->setSpacing(SPACING);
733
734     aLay->addWidget(mySwitchTableGrp, 0, 0, 7, 1);
735     aLay->addWidget(myAddBtn,         0, 1);
736     aLay->addWidget(myInsertBtn,      1, 1);
737     aLay->addWidget(myRemoveBtn,      2, 1);
738     aLay->addWidget(myClearBtn,       3, 1);
739     aLay->addWidget(myCopyFromBtn,    5, 1);
740     aLay->addWidget(myAddToBtn,       6, 1);
741     aLay->addWidget(createAdditionalFrame(myTableGrp), 7, 0, 1, 2 );
742
743     aLay->setRowMinimumHeight(4, 10);
744     aLay->setRowStretch(4, 1);
745     aLay->setColumnStretch(0, 1);
746     aLay->setColumnStretch(1, 0);
747
748     // layout 
749     aMainLay->addWidget(myEntityTypeBox);
750     aMainLay->addWidget(myTableGrp);
751     
752     // signals and slots
753     connect(myAddBtn,    SIGNAL(clicked()), this, SLOT(onAddBtn()));
754     connect(myInsertBtn, SIGNAL(clicked()), this, SLOT(onInsertBtn()));
755     connect(myRemoveBtn, SIGNAL(clicked()), this, SLOT(onRemoveBtn()));
756     connect(myClearBtn,  SIGNAL(clicked()), this, SLOT(onClearBtn()));
757
758     connect(myCopyFromBtn, SIGNAL(clicked()), this, SLOT(onCopyFromBtn()));
759     connect(myAddToBtn,    SIGNAL(clicked()), this, SLOT(onAddToBtn()));
760
761     connect(myEntityTypeGrp, SIGNAL(buttonClicked(int)), this, SLOT(onEntityType(int)));
762
763     myLibDlg = 0;
764   }
765
766   // Hide buttons of entity types if necessary
767   const QMap<int, QString>& aSupportedTypes = getSupportedTypes();
768   QMap<int, QString>::const_iterator anIt;
769   for (anIt = aSupportedTypes.begin(); anIt != aSupportedTypes.end(); ++anIt)
770   {
771     QAbstractButton* aBtn = myEntityTypeGrp->button(anIt.key());
772     if ( aBtn ) aBtn->setVisible( theTypes.contains(anIt.key()) );
773   }
774
775   // select first button if there is no selected buttons or it is hidden
776   int aBtnId = myEntityTypeGrp->checkedId();
777   if ( aBtnId == -1 || !theTypes.contains(aBtnId) ) {
778     QAbstractButton* aBtn = myEntityTypeGrp->button(theTypes.first());
779     if ( aBtn ) aBtn->setChecked(true);
780   }
781
782   myEntityTypeBox->setVisible(theTypes.count() > 1);
783
784   myTableGrp->updateGeometry();
785   int cType = myEntityTypeGrp->checkedId();
786   onEntityType(cType);
787 }
788
789 //=======================================================================
790 // name    : SMESHGUI_FilterTable::createAdditionalFrame
791 // Purpose : Get group box containing table. May be used for adding new widgets in it
792 //=======================================================================
793 QWidget* SMESHGUI_FilterTable::createAdditionalFrame (QWidget* theParent)
794 {
795   QWidget* aFrame = new QWidget(theParent);
796
797   QFrame* aLine1 = new QFrame(aFrame);
798   QFrame* aLine2 = new QFrame(aFrame);
799   aLine1->setFrameStyle(QFrame::HLine | QFrame::Sunken);
800   aLine2->setFrameStyle(QFrame::HLine | QFrame::Sunken);
801   aLine1->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
802   aLine2->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
803
804   QLabel* aLabel = new QLabel(tr("ADDITIONAL_PARAMETERS"), aFrame);
805
806   myWgStack = new QStackedWidget(aFrame);
807
808   QGridLayout* aLay = new QGridLayout(aFrame);
809   aLay->setMargin(0);
810   aLay->setSpacing(SPACING);
811   aLay->addWidget(aLine1,    0, 0);
812   aLay->addWidget(aLabel,    0, 1);
813   aLay->addWidget(aLine2,    0, 2);
814   aLay->addWidget(myWgStack, 1, 0, 1, 3);
815
816   return aFrame;
817 }
818
819 //=======================================================================
820 // name    : SMESHGUI_FilterTable::GetTableGrp
821 // Purpose : Get group box containing table. May be used for adding new widgets in it
822 //=======================================================================
823 QGroupBox* SMESHGUI_FilterTable::GetTableGrp()
824 {
825   return myTableGrp;
826 }
827
828 //=======================================================================
829 // name    : SMESHGUI_FilterTable::onEntityType
830 // Purpose : SLOT. Called when entity type changed.
831 //           Display corresponding table
832 //=======================================================================
833 void SMESHGUI_FilterTable::onEntityType (int theType)
834 {
835   if (myEntityType == theType)
836     return;
837
838   myIsValid = true;
839   emit NeedValidation();
840   if (!myIsValid)
841   {
842     myEntityTypeGrp->button(myEntityType)->setChecked(true);
843     return;
844   }
845
846   myEntityType = theType;
847
848   if (!myTables.contains(theType)) {
849     myTables[ theType ] = createTable(mySwitchTableGrp, theType);
850     ((QVBoxLayout*)mySwitchTableGrp->layout())->addWidget(myTables[ theType ]);
851   }
852
853   TableMap::iterator anIter;
854   for (anIter = myTables.begin(); anIter != myTables.end(); ++anIter)
855      anIter.value()->setVisible( myEntityType == anIter.key() );
856
857   updateBtnState();
858   qApp->processEvents();
859   myTables[ myEntityType ]->updateGeometry();
860   adjustSize();
861
862   emit EntityTypeChanged(theType);
863 }
864
865 //=======================================================================
866 // name    : SMESHGUI_FilterTable::IsValid
867 // Purpose : Verify validity of entered data
868 //=======================================================================
869 bool SMESHGUI_FilterTable::IsValid (const bool theMess, const int theEntityType) const
870 {
871   int aType = theEntityType == -1 ? GetType() : theEntityType;
872
873   Table* aTable = myTables[ aType ];
874   for (int i = 0, n = aTable->rowCount(); i < n; i++)
875   {
876     int aCriterion = GetCriterionType(i, aType);
877
878     if (aCriterion == SMESH::FT_RangeOfIds ||
879          aCriterion == SMESH::FT_BelongToGeom ||
880          aCriterion == SMESH::FT_BelongToPlane ||
881          aCriterion == SMESH::FT_BelongToCylinder ||
882          aCriterion == SMESH::FT_BelongToGenSurface ||
883          aCriterion == SMESH::FT_LyingOnGeom) {
884       if (aTable->text(i, 2).isEmpty()) {
885         if (theMess)
886           SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"),
887                                        tr("ERROR"));
888         return false;
889       }
890     } else {
891       bool aRes = false;
892       bool isSignalsBlocked = aTable->signalsBlocked();
893       aTable->blockSignals(true);
894       double  aThreshold = (int)aTable->text(i, 2).toDouble(&aRes);
895       aTable->blockSignals(isSignalsBlocked);
896
897       if (!aRes && aTable->isEditable(i, 2)) {
898         if (theMess)
899           SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"),
900                                        tr("ERROR"));
901         return false;
902       }
903       else if (aType == SMESH::EDGE &&
904                 GetCriterionType(i, aType) == SMESH::FT_MultiConnection &&
905                 aThreshold == 1)
906       {
907         if (theMess)
908           SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"),
909                                        tr("MULTIEDGES_ERROR"));
910         return false;
911       }
912     }
913
914     QTableWidgetItem* anItem = aTable->item(i, 0);
915     if (myAddWidgets.contains(anItem) && !myAddWidgets[ anItem ]->IsValid())
916       return false;
917   }
918
919   return true;
920 }
921
922 //=======================================================================
923 // name    : SMESHGUI_FilterTable::SetValidity
924 // Purpose : Set validity of the table
925 //=======================================================================
926 void SMESHGUI_FilterTable::SetValidity (const bool isValid)
927 {
928   myIsValid = isValid;
929 }
930
931 //=======================================================================
932 // name    : SMESHGUI_FilterTable::GetType
933 // Purpose : Get current entity type
934 //=======================================================================
935 int SMESHGUI_FilterTable::GetType() const
936 {
937   return myEntityType;
938 }
939
940 //=======================================================================
941 // name    : SMESHGUI_FilterTable::SetType
942 // Purpose : Set current entity type
943 //=======================================================================
944 void SMESHGUI_FilterTable::SetType (const int type)
945 {
946   myEntityTypeGrp->button(type)->setChecked(true);
947   onEntityType(type);
948 }
949
950 //=======================================================================
951 // name    : SMESHGUI_FilterTable::RestorePreviousEntityType
952 // Purpose : Restore previous entity type
953 //=======================================================================
954 void SMESHGUI_FilterTable::RestorePreviousEntityType()
955 {
956   SetType(myEntityType);
957 }
958
959 //=======================================================================
960 // name    : SMESHGUI_FilterTable::GetCriterionType
961 // Purpose : Get type of criterion from specified row (corresponding enums in h-file)
962 //=======================================================================
963 int SMESHGUI_FilterTable::GetCriterionType (const int theRow, const int theType) const
964 {
965   int aType = theType == -1 ? GetType() : theType;
966   Table* aTable = myTables[ aType ];
967   ComboItem* anItem = (ComboItem*)aTable->item(theRow, 0);
968   return anItem != 0 ? anItem->value() : SMESH::FT_Undefined;
969 }
970
971 //=======================================================================
972 // name    : SMESHGUI_FilterTable::GetCriterion
973 // Purpose : Get parameters of criterion from specified row
974 //=======================================================================
975 void SMESHGUI_FilterTable::GetCriterion (const int                 theRow,
976                                          SMESH::Filter::Criterion& theCriterion,
977                                          const int                 theEntityType) const
978 {
979   int aType = theEntityType == -1 ? GetType() : theEntityType;
980   Table* aTable = myTables[ aType ];
981
982   theCriterion.Type = ((ComboItem*)aTable->item(theRow, 0))->value();
983   theCriterion.UnaryOp = ((CheckItem*)aTable->item(theRow, 3))->checked() ? SMESH::FT_LogicalNOT : SMESH::FT_Undefined;
984   theCriterion.BinaryOp = theRow != aTable->rowCount() - 1 ?
985     ((ComboItem*)aTable->item(theRow, 4))->value() : SMESH::FT_Undefined;
986   theCriterion.TypeOfElement = (SMESH::ElementType)aType;
987
988   int aCriterionType = GetCriterionType(theRow, aType);
989
990   if ( aCriterionType != SMESH::FT_RangeOfIds &&
991        aCriterionType != SMESH::FT_BelongToGeom &&
992        aCriterionType != SMESH::FT_BelongToPlane &&
993        aCriterionType != SMESH::FT_BelongToCylinder &&
994        aCriterionType != SMESH::FT_BelongToGenSurface &&
995        aCriterionType != SMESH::FT_LyingOnGeom)
996   {
997     theCriterion.Compare = ((ComboItem*)aTable->item(theRow, 1))->value();
998     theCriterion.Threshold = aTable->item(theRow, 2)->text().toDouble();
999   }
1000   else
1001   {
1002     theCriterion.ThresholdStr = aTable->text(theRow, 2).toLatin1().data();
1003     if ( aCriterionType != SMESH::FT_RangeOfIds )
1004       theCriterion.ThresholdID = aTable->text( theRow, 5 ).toLatin1().data();
1005   }
1006
1007   QTableWidgetItem* anItem = aTable->item(theRow, 0);
1008   if (myAddWidgets.contains(anItem))
1009     theCriterion.Tolerance = myAddWidgets[ anItem ]->GetDouble(AdditionalWidget::Tolerance);
1010 }
1011
1012 //=======================================================================
1013 // name    : SMESHGUI_FilterTable::SetCriterion
1014 // Purpose : Set parameters of criterion of specified row
1015 //=======================================================================
1016 void SMESHGUI_FilterTable::SetCriterion (const int                       theRow,
1017                                          const SMESH::Filter::Criterion& theCriterion,
1018                                          const int                       theEntityType)
1019 {
1020   int aType = theEntityType == -1 ? GetType() : theEntityType;
1021
1022   Table* aTable = myTables[ aType ];
1023
1024   if (theRow > aTable->rowCount() - 1)
1025     return;
1026
1027   ((ComboItem*)aTable->item(theRow, 0))->setValue(theCriterion.Type);
1028   onCriterionChanged(theRow, 0, aType);
1029   ((ComboItem*)aTable->item(theRow, 1))->setValue(theCriterion.Compare);
1030   ((CheckItem*)aTable->item(theRow, 3))->setChecked(theCriterion.UnaryOp == SMESH::FT_LogicalNOT);
1031
1032   if (theCriterion.BinaryOp != SMESH::FT_Undefined)
1033   {
1034     if (!aTable->isEditable(theRow, 4))
1035       aTable->setItem(theRow, 4, getBinaryItem());
1036     ((ComboItem*)aTable->item(theRow, 4))->setValue(theCriterion.BinaryOp);
1037   }
1038   else
1039     aTable->setEditable(false, theRow, 4);
1040
1041   if (theCriterion.Type != SMESH::FT_RangeOfIds &&
1042       theCriterion.Type != SMESH::FT_BelongToGeom &&
1043       theCriterion.Type != SMESH::FT_BelongToPlane &&
1044       theCriterion.Type != SMESH::FT_BelongToCylinder &&
1045       theCriterion.Type != SMESH::FT_BelongToGenSurface &&
1046       theCriterion.Type != SMESH::FT_LyingOnGeom &&
1047       theCriterion.Type != SMESH::FT_FreeBorders &&
1048       theCriterion.Type != SMESH::FT_FreeEdges &&
1049       theCriterion.Type != SMESH::FT_BadOrientedVolume)
1050     aTable->item( theRow, 2 )->setText(QString("%1").arg(theCriterion.Threshold, 0, 'g', 15));
1051   else
1052   {
1053     aTable->item( theRow, 2 )->setText(QString(theCriterion.ThresholdStr));
1054     if ( theCriterion.Type != SMESH::FT_RangeOfIds )
1055       aTable->item( theRow, 5 )->setText( QString( theCriterion.ThresholdID ) );
1056   }
1057
1058   if (theCriterion.Compare == SMESH::FT_EqualTo ||
1059        theCriterion.Type    == SMESH::FT_BelongToPlane ||
1060        theCriterion.Type    == SMESH::FT_BelongToCylinder ||
1061        theCriterion.Type    == SMESH::FT_BelongToGenSurface)
1062   {
1063     QTableWidgetItem* anItem = aTable->item(theRow, 0);
1064     if (!myAddWidgets.contains(anItem))
1065     {
1066       myAddWidgets[ anItem ] = new AdditionalWidget(myWgStack);
1067       myWgStack->addWidget(myAddWidgets[ anItem ]);
1068     }
1069     myAddWidgets[ anItem ]->SetDouble(AdditionalWidget::Tolerance, theCriterion.Tolerance);
1070   }
1071
1072   emit CriterionChanged(theRow, aType);
1073
1074 }
1075
1076 //=======================================================================
1077 // name    : SMESHGUI_FilterTable::Update
1078 // Purpose : Update table
1079 //=======================================================================
1080 void SMESHGUI_FilterTable::Update()
1081 {
1082   Table* aTable = myTables[ GetType() ];
1083   int aCurrRow = aTable->currentRow();
1084   int numRows = aTable->rowCount();
1085   if ((aCurrRow < 0 || aCurrRow >= numRows) && numRows > 0)
1086     aTable->setCurrentCell(0, 0);
1087   updateAdditionalWidget();
1088 }
1089
1090 //=======================================================================
1091 // name    : SMESHGUI_FilterTable::AddCriterion
1092 // Purpose : Add criterion with parameters
1093 //=======================================================================
1094 void SMESHGUI_FilterTable::AddCriterion (const SMESH::Filter::Criterion& theCriterion,
1095                                          const int                       theEntityType)
1096 {
1097   int aType = theEntityType == -1 ? GetType() : theEntityType;
1098   Table* aTable = myTables[ aType ];
1099   addRow(aTable, aType);
1100   SetCriterion(aTable->rowCount() - 1, theCriterion);
1101 }
1102
1103 //=======================================================================
1104 // name    : SMESHGUI_FilterTable::NumRows
1105 // Purpose : Get number of criterions of current type
1106 //=======================================================================
1107 int SMESHGUI_FilterTable::NumRows (const int theEntityType) const
1108 {
1109   return myTables[ theEntityType == -1 ? GetType() : theEntityType ]->rowCount();
1110 }
1111
1112 //=======================================================================
1113 // name    : SMESHGUI_FilterTable::Clear
1114 // Purpose : Clear current table
1115 //=======================================================================
1116 void SMESHGUI_FilterTable::Clear (const int theType)
1117 {
1118   int aType = theType == -1 ? GetType() : theType;
1119   Table* aTable = myTables[ aType ];
1120
1121   if (aTable->rowCount() == 0)
1122     return;
1123
1124   while (aTable->rowCount() > 0)
1125   {
1126     removeAdditionalWidget(aTable, 0);
1127     aTable->removeRow(0);
1128   }
1129
1130   updateBtnState();
1131 }
1132
1133 //=======================================================================
1134 // name    : SMESHGUI_FilterTable::onAddBtn
1135 // Purpose : SLOT. Called then "Add" button pressed.
1136 //           Adds new string to table
1137 //=======================================================================
1138 void SMESHGUI_FilterTable::onAddBtn()
1139 {
1140   int aType = GetType();
1141   addRow(myTables[ aType ], aType);
1142
1143   Update();
1144 }
1145
1146 //=======================================================================
1147 // name    : SMESHGUI_FilterTable::onInsertBtn
1148 // Purpose : SLOT. Called then "Insert" button pressed.
1149 //           Inserts new string before current one
1150 //=======================================================================
1151 void SMESHGUI_FilterTable::onInsertBtn()
1152 {
1153   addRow(myTables[ GetType() ], GetType(), false);
1154 }
1155
1156 //=======================================================================
1157 // name    : SMESHGUI_FilterTable::onRemoveBtn
1158 // Purpose : SLOT. Called then "Remove" button pressed.
1159 //           Removes current string from table
1160 //=======================================================================
1161 void SMESHGUI_FilterTable::onRemoveBtn()
1162 {
1163   Table* aTable = myTables[ GetType() ];
1164
1165   if (aTable->rowCount() == 0)
1166     return;
1167
1168   QList<QTableWidgetItem*> items = aTable->selectedItems();
1169   
1170   QList<int> aRows = aTable->selectedRows(); // already sorted
1171   int i;
1172   foreach( i, aRows )
1173   {
1174     removeAdditionalWidget(aTable, i);
1175     aTable->removeRow(i);
1176   }
1177
1178   // remove control of binary logical operation from last row
1179   if (aTable->rowCount() > 0)
1180     aTable->setEditable(false, aTable->rowCount() - 1, 4);
1181
1182   updateBtnState();
1183 }
1184
1185 //=======================================================================
1186 // name    : SMESHGUI_FilterTable::updateAdditionalWidget
1187 // Purpose : Enable/Disable widget with additonal parameters
1188 //=======================================================================
1189 void SMESHGUI_FilterTable::updateAdditionalWidget()
1190 {
1191   Table* aTable = myTables[ GetType() ];
1192   int aRow = aTable->currentRow();
1193   if (aRow < 0 || aRow >= aTable->rowCount())
1194   {
1195     myWgStack->setEnabled(false);
1196     return;
1197   }
1198
1199   ComboItem* anItem = ((ComboItem*)aTable->item(aRow, 0));
1200   bool toEnable = ((ComboItem*)aTable->item(aRow, 1))->value() == SMESH::FT_EqualTo &&
1201                   GetCriterionType(aRow) != SMESH::FT_BelongToGeom &&
1202                   GetCriterionType(aRow) != SMESH::FT_LyingOnGeom &&
1203                   GetCriterionType(aRow) != SMESH::FT_RangeOfIds &&
1204                   GetCriterionType(aRow) != SMESH::FT_FreeEdges &&
1205                   GetCriterionType(aRow) != SMESH::FT_BadOrientedVolume;
1206   if (!myAddWidgets.contains(anItem))
1207   {
1208     myAddWidgets[ anItem ] = new AdditionalWidget(myWgStack);
1209     myWgStack->addWidget(myAddWidgets[ anItem ]);
1210   }
1211
1212   myWgStack->setCurrentWidget(myAddWidgets[ anItem ]);
1213   myWgStack->setEnabled(toEnable);
1214 }
1215
1216 //=======================================================================
1217 // name    : SMESHGUI_FilterTable::removeAdditionalWidget
1218 // Purpose : Remove widgets containing additional parameters from widget
1219 //           stack and internal map
1220 //=======================================================================
1221 void SMESHGUI_FilterTable::removeAdditionalWidget (QTableWidget* theTable, const int theRow)
1222 {
1223   QTableWidgetItem* anItem = theTable->item(theRow, 0);
1224   if (myAddWidgets.contains(anItem))
1225   {
1226     myWgStack->removeWidget(myAddWidgets[ anItem ]);
1227     myAddWidgets[ anItem ]->setParent(0);
1228     delete myAddWidgets[ anItem ];
1229     myAddWidgets.remove(anItem);
1230   }
1231 }
1232
1233 //=======================================================================
1234 // name    : SMESHGUI_FilterTable::onClearBtn
1235 // Purpose : SLOT. Called then "Clear" button pressed.
1236 //           Removes all strings from table
1237 //=======================================================================
1238 void SMESHGUI_FilterTable::onClearBtn()
1239 {
1240   Table* aTable = myTables[ GetType() ];
1241
1242   if (aTable->rowCount() == 0)
1243     return;
1244
1245   while (aTable->rowCount() > 0)
1246   {
1247     removeAdditionalWidget(aTable, 0);
1248     aTable->removeRow(0);
1249   }
1250
1251   updateBtnState();
1252 }
1253
1254 //=======================================================================
1255 // name    : SMESHGUI_FilterTable::onCurrentChanged()
1256 // Purpose : SLOT. Called when current cell changed
1257 //=======================================================================
1258 void SMESHGUI_FilterTable::onCurrentChanged (int theRow, int theCol)
1259 {
1260   if( !myIsLocked )
1261     updateAdditionalWidget();
1262   emit CurrentChanged(theRow, theCol);
1263 }
1264
1265 //=======================================================================
1266 // name    : SMESHGUI_FilterTable::onCriterionChanged()
1267 // Purpose : Provides reaction on change of criterion
1268 //=======================================================================
1269 void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int col, const int entityType)
1270 {
1271   int aType = entityType == -1 ? GetType() : entityType;
1272   Table* aTable = myTables[ aType ];
1273   ComboItem* aCompareItem = (ComboItem*)aTable->item(row, 1);
1274
1275   int aCriterionType = GetCriterionType(row);
1276
1277   if (aType == SMESH::EDGE && aCriterionType == SMESH::FT_FreeBorders ||
1278        aType == SMESH::FACE && aCriterionType == SMESH::FT_FreeEdges ||
1279        aType == SMESH::VOLUME && aCriterionType == SMESH::FT_BadOrientedVolume)
1280   {
1281     if (aCompareItem->count() > 0)
1282       aCompareItem->clear();
1283     aTable->setEditable(false, row, 2);
1284   }
1285   else if (aCriterionType == SMESH::FT_RangeOfIds ||
1286            aCriterionType == SMESH::FT_BelongToGeom ||
1287            aCriterionType == SMESH::FT_BelongToPlane ||
1288            aCriterionType == SMESH::FT_BelongToCylinder ||
1289            aCriterionType == SMESH::FT_BelongToGenSurface ||
1290            aCriterionType == SMESH::FT_LyingOnGeom)
1291   {
1292     QMap<int, QString> aMap;
1293     aMap[ SMESH::FT_EqualTo ] = tr("EQUAL_TO");
1294     aCompareItem->setItems(aMap);
1295     if (!aTable->isEditable(row, 2))
1296       aTable->setEditable(true, row, 2);
1297   }
1298   else
1299   {
1300     if (aCompareItem->count() != 3)
1301     {
1302       aCompareItem->setItems(getCompare());
1303     }
1304
1305     QString aText = aTable->text(row, 2);
1306     bool isOk = false;
1307     aText.toDouble(&isOk);
1308     aTable->item( row, 2 )->setText(isOk ? aText : QString(""));
1309     if (!aTable->isEditable(row, 2))
1310       aTable->setEditable(true, row, 2);
1311   }
1312
1313   updateAdditionalWidget();
1314
1315   emit CriterionChanged(row, entityType);
1316 }
1317
1318 //=======================================================================
1319 // name    : SMESHGUI_FilterTable::onCriterionChanged()
1320 // Purpose : SLOT. Called then contents of table changed
1321 //           Provides reaction on change of criterion
1322 //=======================================================================
1323 void SMESHGUI_FilterTable::onCriterionChanged (int row, int col)
1324 {
1325   onCriterionChanged(row, col, -1);
1326 }
1327
1328 //=======================================================================
1329 // name    : SMESHGUI_FilterTable::getFirstSelectedRow
1330 // Purpose : Get first selected row
1331 //=======================================================================
1332 int SMESHGUI_FilterTable::getFirstSelectedRow() const
1333 {
1334   Table* aTable = myTables[ GetType() ];
1335
1336   QList<int> selRows = aTable->selectedRows(); // already sorted
1337   int aRow = selRows.count() > 0 ? selRows[0] : aTable->currentRow();
1338
1339   return aRow >= 0 && aRow < aTable->rowCount() ? aRow : -1;
1340 }
1341
1342 //=======================================================================
1343 // name    : SMESHGUI_FilterTable::addRow
1344 // Purpose : Add row at the end of table
1345 //=======================================================================
1346 void SMESHGUI_FilterTable::addRow (Table* theTable, const int theType, const bool toTheEnd)
1347 {
1348   int aCurrRow = 0;
1349   int aSelectedRow = getFirstSelectedRow();
1350   int aCurrCol = theTable->currentColumn();
1351
1352   myIsLocked = true;
1353   if (toTheEnd || aSelectedRow == -1)
1354   {
1355     theTable->insertRows(theTable->rowCount());
1356     aCurrRow = theTable->rowCount() - 1;
1357   }
1358   else
1359   {
1360     theTable->insertRows(aSelectedRow);
1361     aCurrRow = aSelectedRow;
1362   }
1363   myIsLocked = false;
1364
1365   // IPAL19372 - to prevent calling onCriterionChaged() slot before completion of setItem()
1366   bool isSignalsBlocked = theTable->signalsBlocked();
1367   theTable->blockSignals( true );
1368
1369   // Criteria
1370   theTable->setItem(aCurrRow, 0, getCriterionItem(theType));
1371
1372   // Compare
1373   theTable->setItem(aCurrRow, 1, getCompareItem());
1374
1375   // Threshold
1376   theTable->setItem(aCurrRow, 2, new QTableWidgetItem());
1377
1378   // Logical operation NOT
1379   theTable->setItem(aCurrRow, 3, getUnaryItem());
1380
1381   // Logical operation AND / OR
1382   theTable->setItem(aCurrRow, 4, new QTableWidgetItem());
1383
1384   theTable->blockSignals( isSignalsBlocked );
1385
1386   // Logical binary operation for previous value
1387   int anAddBinOpStr = -1;
1388   if (aCurrRow == theTable->rowCount() - 1)
1389     anAddBinOpStr = aCurrRow - 1;
1390   else if (aCurrRow >= 0 )
1391     anAddBinOpStr = aCurrRow;
1392
1393   if (theTable->item(aCurrRow, 4) == 0 ||
1394        theTable->item(aCurrRow, 4)->type() != ComboItem::Type())
1395   {
1396
1397
1398     if (anAddBinOpStr >= 0 &&
1399          (theTable->item(anAddBinOpStr, 4) == 0 ||
1400            theTable->item(anAddBinOpStr, 4)->type() != ComboItem::Type()))
1401       theTable->setItem(anAddBinOpStr, 4, getBinaryItem());
1402   }
1403
1404   theTable->setEditable(false, theTable->rowCount() - 1, 4);
1405
1406   if (aCurrRow >=0 && aCurrRow < theTable->rowCount() &&
1407        aCurrCol >=0 && aCurrCol < theTable->rowCount())
1408   theTable->setCurrentCell(aCurrRow, aCurrCol);
1409
1410   onCriterionChanged(aCurrRow, 0);
1411
1412   updateBtnState();
1413 }
1414
1415 //=======================================================================
1416 // name    : SMESHGUI_FilterTable::getCriterionItem
1417 // Purpose : Get combo table item for criteria of specified type
1418 //=======================================================================
1419 QTableWidgetItem* SMESHGUI_FilterTable::getCriterionItem (const int theType) const
1420 {
1421   return new ComboItem(getCriteria(theType));
1422 }
1423
1424 //=======================================================================
1425 // name    : SMESHGUI_FilterTable::getCompareItem
1426 // Purpose : Get combo table item for operation of comparision
1427 //=======================================================================
1428 QTableWidgetItem* SMESHGUI_FilterTable::getCompareItem () const
1429 {
1430   return new ComboItem(getCompare());
1431 }
1432
1433 //=======================================================================
1434 // name    : SMESHGUI_FilterTable::getBinaryItem
1435 // Purpose :
1436 //=======================================================================
1437 QTableWidgetItem* SMESHGUI_FilterTable::getBinaryItem () const
1438 {
1439   static QMap<int, QString> aMap;
1440   if (aMap.isEmpty())
1441   {
1442     aMap[ SMESH::FT_LogicalAND ] = tr("AND");
1443     aMap[ SMESH::FT_LogicalOR  ] = tr("OR");
1444   }
1445
1446   return new ComboItem(aMap);
1447 }
1448
1449 //=======================================================================
1450 // name    : SMESHGUI_FilterTable::getUnaryItem
1451 // Purpose : Get check table item
1452 //=======================================================================
1453 QTableWidgetItem* SMESHGUI_FilterTable::getUnaryItem () const
1454 {
1455   return new CheckItem(tr("NOT"));
1456 }
1457
1458 //=======================================================================
1459 // name    : SMESHGUI_FilterTable::getSupportedTypes
1460 // Purpose : Get all supported type
1461 //=======================================================================
1462 const QMap<int, QString>& SMESHGUI_FilterTable::getSupportedTypes() const
1463 {
1464   static QMap<int, QString> aTypes;
1465   if (aTypes.isEmpty())
1466   {
1467     aTypes[ SMESH::NODE   ] = tr("NODES");
1468     aTypes[ SMESH::EDGE   ] = tr("EDGES");
1469     aTypes[ SMESH::FACE   ] = tr("FACES");
1470     aTypes[ SMESH::VOLUME ] = tr("VOLUMES");
1471   }
1472
1473   return aTypes;
1474 }
1475
1476 //=======================================================================
1477 // name    : SMESHGUI_FilterTable::getCriteria
1478 // Purpose : Get criteria for specified type
1479 //=======================================================================
1480 const QMap<int, QString>& SMESHGUI_FilterTable::getCriteria (const int theType) const
1481 {
1482   if (theType == SMESH::NODE)
1483   {
1484     static QMap<int, QString> aCriteria;
1485     if (aCriteria.isEmpty())
1486     {
1487       aCriteria[ SMESH::FT_RangeOfIds         ] = tr("RANGE_OF_IDS");
1488       aCriteria[ SMESH::FT_BelongToGeom       ] = tr("BELONG_TO_GEOM");
1489       aCriteria[ SMESH::FT_BelongToPlane      ] = tr("BELONG_TO_PLANE");
1490       aCriteria[ SMESH::FT_BelongToCylinder   ] = tr("BELONG_TO_CYLINDER");
1491       aCriteria[ SMESH::FT_BelongToGenSurface ] = tr("BELONG_TO_GENSURFACE");
1492       aCriteria[ SMESH::FT_LyingOnGeom        ] = tr("LYING_ON_GEOM");
1493     }
1494     return aCriteria;
1495   }
1496   else if (theType == SMESH::EDGE)
1497   {
1498     static QMap<int, QString> aCriteria;
1499     if (aCriteria.isEmpty())
1500     {
1501       aCriteria[ SMESH::FT_FreeBorders        ] = tr("FREE_BORDERS");
1502       aCriteria[ SMESH::FT_MultiConnection    ] = tr("MULTI_BORDERS");
1503       aCriteria[ SMESH::FT_Length             ] = tr("LENGTH");
1504       aCriteria[ SMESH::FT_RangeOfIds         ] = tr("RANGE_OF_IDS");
1505       aCriteria[ SMESH::FT_BelongToGeom       ] = tr("BELONG_TO_GEOM");
1506       aCriteria[ SMESH::FT_BelongToPlane      ] = tr("BELONG_TO_PLANE");
1507       aCriteria[ SMESH::FT_BelongToCylinder   ] = tr("BELONG_TO_CYLINDER");
1508       aCriteria[ SMESH::FT_BelongToGenSurface ] = tr("BELONG_TO_GENSURFACE");
1509       aCriteria[ SMESH::FT_LyingOnGeom        ] = tr("LYING_ON_GEOM");
1510     }
1511     return aCriteria;
1512   }
1513   else if (theType == SMESH::FACE)
1514   {
1515     static QMap<int, QString> aCriteria;
1516     if (aCriteria.isEmpty())
1517     {
1518       aCriteria[ SMESH::FT_AspectRatio        ] = tr("ASPECT_RATIO");
1519       aCriteria[ SMESH::FT_Warping            ] = tr("WARPING");
1520       aCriteria[ SMESH::FT_MinimumAngle       ] = tr("MINIMUM_ANGLE");
1521       aCriteria[ SMESH::FT_Taper              ] = tr("TAPER");
1522       aCriteria[ SMESH::FT_Skew               ] = tr("SKEW");
1523       aCriteria[ SMESH::FT_Area               ] = tr("AREA");
1524       aCriteria[ SMESH::FT_FreeEdges          ] = tr("FREE_EDGES");
1525       aCriteria[ SMESH::FT_RangeOfIds         ] = tr("RANGE_OF_IDS");
1526       aCriteria[ SMESH::FT_BelongToGeom       ] = tr("BELONG_TO_GEOM");
1527       aCriteria[ SMESH::FT_BelongToPlane      ] = tr("BELONG_TO_PLANE");
1528       aCriteria[ SMESH::FT_BelongToCylinder   ] = tr("BELONG_TO_CYLINDER");
1529       aCriteria[ SMESH::FT_BelongToGenSurface ] = tr("BELONG_TO_GENSURFACE");
1530       aCriteria[ SMESH::FT_LyingOnGeom        ] = tr("LYING_ON_GEOM");
1531       aCriteria[ SMESH::FT_Length2D           ] = tr("LENGTH2D");
1532       aCriteria[ SMESH::FT_MultiConnection2D  ] = tr("MULTI2D_BORDERS");
1533     }
1534     return aCriteria;
1535   }
1536   else if (theType == SMESH::VOLUME)
1537   {
1538     static QMap<int, QString> aCriteria;
1539     if (aCriteria.isEmpty())
1540     {
1541       aCriteria[ SMESH::FT_AspectRatio3D     ] = tr("ASPECT_RATIO_3D");
1542       aCriteria[ SMESH::FT_RangeOfIds        ] = tr("RANGE_OF_IDS");
1543       aCriteria[ SMESH::FT_BelongToGeom      ] = tr("BELONG_TO_GEOM");
1544       aCriteria[ SMESH::FT_LyingOnGeom       ] = tr("LYING_ON_GEOM");
1545       aCriteria[ SMESH::FT_BadOrientedVolume ] = tr("BAD_ORIENTED_VOLUME");
1546       aCriteria[ SMESH::FT_Volume3D          ] = tr("VOLUME_3D");
1547     }
1548     return aCriteria;
1549   }
1550   else
1551   {
1552     static QMap<int, QString> aCriteria;
1553     return aCriteria;
1554   }
1555 }
1556
1557
1558 //=======================================================================
1559 // name    : SMESHGUI_FilterTable::getCompare
1560 // Purpose : Get operation of comparison
1561 //=======================================================================
1562 const QMap<int, QString>& SMESHGUI_FilterTable::getCompare() const
1563 {
1564   static QMap<int, QString> aMap;
1565
1566   if (aMap.isEmpty())
1567   {
1568     aMap[ SMESH::FT_LessThan ] = tr("LESS_THAN");
1569     aMap[ SMESH::FT_MoreThan ] = tr("MORE_THAN");
1570     aMap[ SMESH::FT_EqualTo  ] = tr("EQUAL_TO" );
1571   }
1572
1573   return aMap;
1574 }
1575
1576 //=======================================================================
1577 // name    : SMESHGUI_FilterTable::createTable
1578 // Purpose : Create table
1579 //=======================================================================
1580 SMESHGUI_FilterTable::Table* SMESHGUI_FilterTable::createTable (QWidget*  theParent,
1581                                                                 const int theType)
1582 {
1583   // create table
1584   Table* aTable= new Table(0, 6, theParent);
1585
1586   QHeaderView* aHeaders = aTable->horizontalHeader();
1587
1588   QFontMetrics aMetrics(aHeaders->font());
1589
1590   // append spaces to the header of criteria in order to
1591   // provide visibility of criterion inside comboboxes
1592   static int aMaxLenCr = 0;
1593
1594   if (aMaxLenCr == 0)
1595   {
1596     const QMap<int, QString>& aSupportedTypes = getSupportedTypes();
1597     QMap<int, QString>::const_iterator anIter;
1598     for (anIter = aSupportedTypes.begin(); anIter != aSupportedTypes.end(); ++anIter)
1599       aMaxLenCr = qMax(maxLength(getCriteria(anIter.key()), aMetrics), aMaxLenCr);
1600   }
1601
1602   static int aLenCr = qAbs( aMaxLenCr -
1603                             aMetrics.width(tr("CRITERION"))) / aMetrics.width(' ') + 5;
1604
1605   QString aCrStr;
1606   aCrStr.fill(' ', aLenCr);
1607   QString aCoStr;
1608   aCoStr.fill(' ', 10);
1609
1610   QStringList aHeaderLabels;
1611   aHeaderLabels.append( tr("CRITERION") + aCrStr );
1612   aHeaderLabels.append( tr("COMPARE")   + aCoStr );
1613   aHeaderLabels.append( tr("THRESHOLD_VALUE") );
1614   aHeaderLabels.append( tr("UNARY") );
1615   aHeaderLabels.append( tr("BINARY") + "  " );
1616   aHeaderLabels.append( tr("ID") );
1617   aTable->setHorizontalHeaderLabels( aHeaderLabels );
1618
1619   // set geometry of the table
1620   for (int i = 0; i <= 4; i++)
1621     aTable->resizeColumnToContents(i);
1622
1623   // set the ID column invisible
1624   aTable->hideColumn( 5 );
1625
1626   aTable->updateGeometry();
1627   QSize aSize = aTable->sizeHint();
1628   int aWidth = aSize.width();
1629   aTable->setMinimumSize(QSize(aWidth, aWidth / 2));
1630   aTable->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));
1631
1632   connect(aTable, SIGNAL(cellChanged(int, int)),
1633           this,   SLOT(onCriterionChanged(int, int)));
1634
1635   connect(aTable, SIGNAL(currentCellChanged(int, int, int, int)),
1636           this,   SLOT(onCurrentChanged(int, int)));
1637   
1638   return aTable;
1639 }
1640
1641 //=======================================================================
1642 // name    : SMESHGUI_FilterTable::updateBtnState
1643 // Purpose : Update button state
1644 //=======================================================================
1645 void SMESHGUI_FilterTable::updateBtnState()
1646 {
1647   myRemoveBtn->setEnabled(myTables[ GetType() ]->rowCount() > 0);
1648   myClearBtn->setEnabled(myTables[ GetType() ]->rowCount() > 0);
1649 }
1650
1651 //=======================================================================
1652 // name    : SMESHGUI_FilterTable::SetEditable
1653 // Purpose : Set read only flag for tables. Show/hide buttons for work with rows
1654 //=======================================================================
1655 void SMESHGUI_FilterTable::SetEditable (const bool isEditable)
1656 {
1657   TableMap::iterator anIter;
1658   for (anIter = myTables.begin(); anIter != myTables.end(); ++anIter)
1659   {
1660     anIter.value()->setReadOnly(!isEditable);
1661
1662     if (isEditable)
1663     {
1664       myAddBtn->show();
1665       myInsertBtn->show();
1666       myRemoveBtn->show();
1667       myClearBtn->show();
1668     }
1669     else
1670     {
1671       myAddBtn->hide();
1672       myInsertBtn->hide();
1673       myRemoveBtn->hide();
1674       myClearBtn->hide();
1675     }
1676   }
1677
1678   QMap<QTableWidgetItem*, AdditionalWidget*>::iterator anIter2;
1679   for (anIter2 = myAddWidgets.begin(); anIter2 != myAddWidgets.end(); ++anIter2)
1680     anIter2.value()->SetEditable(isEditable);
1681 }
1682
1683 //=======================================================================
1684 // name    : SMESHGUI_FilterTable::SetEnabled
1685 // Purpose : Enable/Disable table. Switching type of elements already enabled
1686 //=======================================================================
1687 void SMESHGUI_FilterTable::SetEnabled (const bool isEnabled)
1688 {
1689   myAddBtn->setEnabled(isEnabled);
1690   myInsertBtn->setEnabled(isEnabled);
1691   myRemoveBtn->setEnabled(isEnabled);
1692   myClearBtn->setEnabled(isEnabled);
1693
1694   if (isEnabled)
1695     updateBtnState();
1696
1697   QMap<QTableWidgetItem*, AdditionalWidget*>::iterator anIter2;
1698   for (anIter2 = myAddWidgets.begin(); anIter2 != myAddWidgets.end(); ++anIter2)
1699     anIter2.value()->setEnabled(isEnabled);
1700 }
1701
1702 //=======================================================================
1703 // name    : SMESHGUI_FilterTable::IsEditable
1704 // Purpose : Verify whether table is editable
1705 //=======================================================================
1706 bool SMESHGUI_FilterTable::IsEditable() const
1707 {
1708   return !myTables[ GetType() ]->isReadOnly();
1709 }
1710
1711 //=======================================================================
1712 // name    : SMESHGUI_FilterTable::SetLibsEnabled
1713 // Purpose : Show/hide buttons for work with libraries
1714 //=======================================================================
1715 void SMESHGUI_FilterTable::SetLibsEnabled (const bool isEnabled)
1716 {
1717   if (isEnabled)
1718   {
1719     myCopyFromBtn->show();
1720     myAddToBtn->show();
1721   }
1722   else
1723   {
1724     myCopyFromBtn->hide();
1725     myAddToBtn->hide();
1726   }
1727 }
1728
1729 //=======================================================================
1730 // name    : SMESHGUI_FilterTable::onCopyFromBtn
1731 // Purpose : SLOT. Called the "Copy from ..." button clicked
1732 //           Display filter library dialog
1733 //=======================================================================
1734 void SMESHGUI_FilterTable::onCopyFromBtn()
1735 {
1736   if (myLibDlg == 0)
1737     myLibDlg = new SMESHGUI_FilterLibraryDlg(
1738       mySMESHGUI, this, GetType(), SMESHGUI_FilterLibraryDlg::COPY_FROM);
1739   else
1740     myLibDlg->Init(GetType(), SMESHGUI_FilterLibraryDlg::COPY_FROM);
1741
1742   if (myLibDlg->exec() == QDialog::Accepted)
1743   {
1744     Copy(myLibDlg->GetTable());
1745     Update();
1746   }
1747 }
1748
1749 //=======================================================================
1750 // name    : SMESHGUI_FilterTable::onAddToBtn
1751 // Purpose : SLOT. Called the "Add to ..." button clicked
1752 //           Display filter library dialog
1753 //=======================================================================
1754 void SMESHGUI_FilterTable::onAddToBtn()
1755 {
1756   if (!IsValid(true))
1757     return;
1758   if (myLibDlg == 0)
1759     myLibDlg = new SMESHGUI_FilterLibraryDlg(
1760       mySMESHGUI, this, GetType(), SMESHGUI_FilterLibraryDlg::ADD_TO);
1761   else
1762     myLibDlg->Init(GetType(), SMESHGUI_FilterLibraryDlg::ADD_TO);
1763
1764   myLibDlg->SetTable(this);
1765
1766   myLibDlg->exec();
1767 }
1768
1769 //=======================================================================
1770 // name    : SMESHGUI_FilterTable::Copy
1771 // Purpose : Initialise table with values of other table
1772 //=======================================================================
1773 void SMESHGUI_FilterTable::Copy (const SMESHGUI_FilterTable* theTable)
1774 {
1775   Clear();
1776
1777   for (int i = 0, n = theTable->NumRows(); i < n; i++)
1778   {
1779     SMESH::Filter::Criterion aCriterion = SMESHGUI_FilterDlg::createCriterion();
1780     theTable->GetCriterion(i, aCriterion);
1781     AddCriterion(aCriterion);
1782   }
1783 }
1784
1785 //=======================================================================
1786 // name    : SMESHGUI_FilterTable::CurrentCell
1787 // Purpose : Returns current cell
1788 //=======================================================================
1789 bool SMESHGUI_FilterTable::CurrentCell (int& theRow, int& theCol) const
1790 {
1791   theRow = myTables[ GetType() ]->currentRow();
1792   theCol = myTables[ GetType() ]->currentColumn();
1793   return theRow >= 0 && theCol >= 0;
1794 }
1795
1796 //=======================================================================
1797 // name    : SMESHGUI_FilterTable::SetText
1798 // Purpose : Set text and internal value in cell of threshold value
1799 //=======================================================================
1800 void SMESHGUI_FilterTable::SetThreshold (const int      theRow,
1801                                          const QString& theText,
1802                                          const int      theEntityType)
1803 {
1804   Table* aTable = myTables[ theEntityType == -1 ? GetType() : theEntityType ];
1805   aTable->item( theRow, 2 )->setText(theText);
1806 }
1807
1808 //=======================================================================
1809 // name    : SMESHGUI_FilterTable::SetText
1810 // Purpose : Get text and internal value from cell of threshold value
1811 //=======================================================================
1812 bool SMESHGUI_FilterTable::GetThreshold (const int      theRow,
1813                                          QString&       theText,
1814                                          const int      theEntityType)
1815 {
1816   Table* aTable = myTables[ theEntityType == -1 ? GetType() : theEntityType ];
1817   QTableWidgetItem* anItem = aTable->item(theRow, 2);
1818   if (anItem != 0)
1819   {
1820     theText = anItem->text();
1821     return true;
1822   }
1823   else
1824    return false;
1825 }
1826
1827 //=======================================================================
1828 // name    : SMESHGUI_FilterTable::SetID
1829 // Purpose : Set text and internal value in cell of ID value 
1830 //=======================================================================
1831 void SMESHGUI_FilterTable::SetID( const int      theRow,
1832                                          const QString& theText,
1833                                          const int      theEntityType )
1834 {
1835   Table* aTable = myTables[ theEntityType == -1 ? GetType() : theEntityType ];
1836   aTable->item( theRow, 5 )->setText( theText );
1837 }
1838
1839 //=======================================================================
1840 // name    : SMESHGUI_FilterTable::GetID
1841 // Purpose : Get text and internal value from cell of ID value
1842 //=======================================================================
1843 bool SMESHGUI_FilterTable::GetID( const int      theRow,
1844                                   QString&       theText,
1845                                   const int      theEntityType )
1846 {
1847   Table* aTable = myTables[ theEntityType == -1 ? GetType() : theEntityType ];
1848   QTableWidgetItem* anItem = aTable->item( theRow, 5 );
1849   if ( anItem != 0 )
1850     {
1851       theText = anItem->text();
1852       return true;    
1853     }
1854   else
1855     return false;
1856
1857
1858 /*
1859   Class       : SMESHGUI_FilterDlg
1860   Description : Dialog to specify filters for VTK viewer
1861 */
1862
1863
1864 //=======================================================================
1865 // name    : SMESHGUI_FilterDlg::SMESHGUI_FilterDlg
1866 // Purpose : Constructor
1867 //=======================================================================
1868 SMESHGUI_FilterDlg::SMESHGUI_FilterDlg( SMESHGUI*         theModule,
1869                                         const QList<int>& theTypes )
1870 : QDialog( SMESH::GetDesktop( theModule ) ),
1871   mySMESHGUI( theModule ),
1872   mySelectionMgr( SMESH::GetSelectionMgr( theModule ) )
1873 {
1874   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1875     mySelector = aViewWindow->GetSelector();
1876
1877   construct(theTypes);
1878 }
1879
1880 //=======================================================================
1881 // name    : SMESHGUI_FilterDlg::SMESHGUI_FilterDlg
1882 // Purpose : Constructor
1883 //=======================================================================
1884 SMESHGUI_FilterDlg::SMESHGUI_FilterDlg( SMESHGUI*   theModule,
1885                                         const int   theType )
1886 : QDialog( SMESH::GetDesktop( theModule ) ),
1887   mySMESHGUI( theModule ),
1888   mySelectionMgr( SMESH::GetSelectionMgr( theModule ) )
1889 {
1890   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
1891     mySelector = aViewWindow->GetSelector();
1892   QList<int> aTypes;
1893   aTypes.append(theType);
1894   construct(aTypes);
1895 }
1896
1897 //=======================================================================
1898 // name    : SMESHGUI_FilterDlg::construct
1899 // Purpose : Construct dialog (called by constructor)
1900 //=======================================================================
1901 void SMESHGUI_FilterDlg::construct (const QList<int>& theTypes)
1902 {
1903   myTypes = theTypes;
1904
1905   setModal(false);
1906   //setAttribute(Qt::WA_DeleteOnClose, true); // VSR ??? is it required?
1907   setWindowTitle(tr("CAPTION"));
1908
1909   QVBoxLayout* aDlgLay = new QVBoxLayout (this);
1910   aDlgLay->setMargin(MARGIN);
1911   aDlgLay->setSpacing(SPACING);
1912
1913   myMainFrame         = createMainFrame  (this);
1914   QWidget* aBtnFrame  = createButtonFrame(this);
1915
1916   aDlgLay->addWidget(myMainFrame);
1917   aDlgLay->addWidget(aBtnFrame);
1918
1919   aDlgLay->setStretchFactor(myMainFrame, 1);
1920
1921   myHelpFileName = "selection_filter_library_page.html";
1922
1923   Init(myTypes);
1924 }
1925
1926 //=======================================================================
1927 // name    : SMESHGUI_FilterDlg::createMainFrame
1928 // Purpose : Create frame containing dialog's input fields
1929 //=======================================================================
1930 QWidget* SMESHGUI_FilterDlg::createMainFrame (QWidget* theParent)
1931 {
1932   QWidget* aMainFrame = new QWidget(theParent);
1933   QVBoxLayout* aMainLay = new QVBoxLayout(aMainFrame);
1934   aMainLay->setMargin(0);
1935   aMainLay->setSpacing(SPACING);
1936
1937   // filter frame
1938
1939   myTable = new SMESHGUI_FilterTable( mySMESHGUI, aMainFrame, myTypes );
1940   myTable->SetLibsEnabled(true);
1941
1942   QGroupBox* aGrp = myTable->GetTableGrp();
1943   QGridLayout* aLay = qobject_cast<QGridLayout*>( aGrp->layout() );
1944   int rows = aLay->rowCount();
1945   int cols = aLay->columnCount();
1946
1947   QFrame* aLine = new QFrame(aGrp);
1948   aLine->setFrameStyle(QFrame::HLine | QFrame::Sunken);
1949   aLay->addWidget(aLine, rows++, 0, 1, cols);
1950
1951   mySetInViewer = new QCheckBox(tr("SET_IN_VIEWER"), aGrp);
1952   mySetInViewer->setChecked(true);
1953   aLay->addWidget(mySetInViewer, rows++, 0, 1, cols);
1954
1955   // other controls
1956   QWidget* aSourceGrp = createSourceGroup(aMainFrame);
1957
1958   connect(myTable, SIGNAL(CriterionChanged(const int, const int)),
1959                     SLOT(onCriterionChanged(const int, const int)));
1960
1961   connect(myTable, SIGNAL(CurrentChanged(int, int)),
1962                     SLOT(onCurrentChanged(int, int)));
1963
1964   aMainLay->addWidget(myTable);
1965   aMainLay->addWidget(aSourceGrp);
1966   
1967   return aMainFrame;
1968 }
1969
1970 //=======================================================================
1971 // name    : SMESHGUI_FilterDlg::createSourceFrame
1972 // Purpose : Create frame containing source radio button
1973 //=======================================================================
1974 QWidget* SMESHGUI_FilterDlg::createSourceGroup (QWidget* theParent)
1975 {
1976   QGroupBox* aBox = new QGroupBox(tr("SOURCE"), theParent);
1977   QHBoxLayout* aLay = new QHBoxLayout(aBox);
1978   aLay->setMargin(MARGIN);
1979   aLay->setSpacing(SPACING);
1980
1981   mySourceGrp = new QButtonGroup(theParent);
1982
1983   QRadioButton* aMeshBtn = new QRadioButton(tr("MESH"),          aBox);
1984   QRadioButton* aSelBtn  = new QRadioButton(tr("SELECTION"),     aBox);
1985   QRadioButton* aGrpBtn  = new QRadioButton(tr("CURRENT_GROUP"), aBox);
1986
1987   aLay->addWidget(aMeshBtn);
1988   aLay->addWidget(aSelBtn);
1989   aLay->addWidget(aGrpBtn);
1990
1991   mySourceGrp->addButton(aMeshBtn, Mesh);
1992   mySourceGrp->addButton(aSelBtn,  Selection);
1993   mySourceGrp->addButton(aGrpBtn,  Dialog);
1994
1995   aSelBtn->setChecked(true);
1996
1997   return aBox;
1998 }
1999
2000 //=======================================================================
2001 // name    : SMESHGUI_FilterDlg::updateMainButtons
2002 // Purpose : Update visibility of main buttons (OK, Cancel, Close ...)
2003 //=======================================================================
2004 void SMESHGUI_FilterDlg::updateMainButtons()
2005 {
2006   if (myTypes.count() == 1)
2007   {
2008     myButtons[ BTN_Cancel ]->show();
2009     myButtons[ BTN_Apply  ]->hide();
2010     myButtons[ BTN_Close  ]->hide();
2011   }
2012   else
2013   {
2014     myButtons[ BTN_Cancel ]->hide();
2015     myButtons[ BTN_Apply  ]->show();
2016     myButtons[ BTN_Close  ]->show();
2017   }
2018
2019 //  updateGeometry();
2020 }
2021
2022 //=======================================================================
2023 // name    : SMESHGUI_FilterDlg::createButtonFrame
2024 // Purpose : Create frame containing buttons
2025 //=======================================================================
2026 QWidget* SMESHGUI_FilterDlg::createButtonFrame (QWidget* theParent)
2027 {
2028   QGroupBox* aGrp = new QGroupBox(theParent);
2029   QHBoxLayout* aLay = new QHBoxLayout(aGrp);
2030   aLay->setMargin(MARGIN);
2031   aLay->setSpacing(SPACING);
2032
2033   myButtons[ BTN_OK     ] = new QPushButton(tr("SMESH_BUT_OK"   ),  aGrp);
2034   myButtons[ BTN_Apply  ] = new QPushButton(tr("SMESH_BUT_APPLY"),  aGrp);
2035   myButtons[ BTN_Cancel ] = new QPushButton(tr("SMESH_BUT_CANCEL"), aGrp);
2036   myButtons[ BTN_Close  ] = new QPushButton(tr("SMESH_BUT_CLOSE"),  aGrp);
2037   myButtons[ BTN_Help   ] = new QPushButton(tr("SMESH_BUT_HELP"),   aGrp);
2038
2039   aLay->addWidget(myButtons[ BTN_OK     ]);
2040   aLay->addSpacing(10);
2041   aLay->addWidget(myButtons[ BTN_Apply  ]);
2042   aLay->addSpacing(10);
2043   aLay->addStretch();
2044   aLay->addWidget(myButtons[ BTN_Cancel ]);
2045   aLay->addWidget(myButtons[ BTN_Close  ]);
2046   aLay->addWidget(myButtons[ BTN_Help   ]);
2047
2048   connect(myButtons[ BTN_OK     ], SIGNAL(clicked()), SLOT(onOk()));
2049   connect(myButtons[ BTN_Cancel ], SIGNAL(clicked()), SLOT(onClose()));
2050   connect(myButtons[ BTN_Close  ], SIGNAL(clicked()), SLOT(onClose()));
2051   connect(myButtons[ BTN_Apply  ], SIGNAL(clicked()), SLOT(onApply()));
2052   connect(myButtons[ BTN_Help   ], SIGNAL(clicked()), SLOT(onHelp()));
2053
2054   updateMainButtons();
2055
2056   return aGrp;
2057 }
2058
2059 //=======================================================================
2060 // name    : SMESHGUI_FilterDlg::~SMESHGUI_FilterDlg
2061 // Purpose : Destructor
2062 //=======================================================================
2063 SMESHGUI_FilterDlg::~SMESHGUI_FilterDlg()
2064 {
2065 }
2066
2067 //=======================================================================
2068 // name    : SMESHGUI_FilterDlg::Init
2069 // Purpose : Init dialog fields, connect signals and slots, show dialog
2070 //=======================================================================
2071 void SMESHGUI_FilterDlg::Init (const int type)
2072 {
2073   QList<int> aTypes;
2074   aTypes.append(type);
2075   Init(aTypes);
2076 }
2077
2078 //=======================================================================
2079 // name    : SMESHGUI_FilterDlg::Init
2080 // Purpose : Init dialog fields, connect signals and slots, show dialog
2081 //=======================================================================
2082 void SMESHGUI_FilterDlg::Init (const QList<int>& theTypes)
2083 {
2084   mySourceWg  = 0;
2085   myTypes     = theTypes;
2086   myMesh      = SMESH::SMESH_Mesh::_nil();
2087   myIObjects.Clear();
2088   myIsSelectionChanged = false;
2089
2090   myTable->Init(theTypes);
2091
2092   // set caption
2093   if (theTypes.count() == 1)
2094   {
2095     int aType = theTypes.first();
2096     if      (aType == SMESH::NODE  ) setWindowTitle(tr("NODES_TLT"));
2097     else if (aType == SMESH::EDGE  ) setWindowTitle(tr("EDGES_TLT"));
2098     else if (aType == SMESH::FACE  ) setWindowTitle(tr("FACES_TLT"));
2099     else if (aType == SMESH::VOLUME) setWindowTitle(tr("VOLUMES_TLT"));
2100   }
2101   else
2102     setWindowTitle(tr("TLT"));
2103
2104   qApp->processEvents();
2105   updateGeometry();
2106   adjustSize();
2107   setEnabled(true);
2108
2109   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
2110
2111   connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
2112   connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(onClose()));
2113   
2114   updateMainButtons();
2115   updateSelection();
2116
2117   // Initialise filter table with values of previous filter
2118   QList<int>::const_iterator anIter;
2119   for (anIter = theTypes.begin(); anIter != theTypes.end(); ++anIter)
2120   {
2121     myTable->Clear(*anIter);
2122     if (!myFilter[ *anIter ]->_is_nil())
2123     {
2124       SMESH::Filter::Criteria_var aCriteria = new SMESH::Filter::Criteria;
2125       if (myFilter[ *anIter ]->GetCriteria(aCriteria))
2126       {
2127         for (int i = 0, n = aCriteria->length(); i < n; i++)
2128           myTable->AddCriterion(aCriteria[ i ], *anIter);
2129       }
2130     }
2131   }
2132
2133   if (myInsertState.contains(theTypes.first()))
2134     mySetInViewer->setChecked(myInsertState[ theTypes.first() ]);
2135   else
2136     mySetInViewer->setChecked(true);
2137
2138   mySourceGrp->button(myApplyToState.contains(theTypes.first()) ? 
2139                       myApplyToState[ theTypes.first() ] :
2140                       Selection)->setChecked(true);
2141 }
2142
2143 //=======================================================================
2144 // name    : SMESHGUI_FilterDlg::onOk
2145 // Purpose : SLOT called when "Ok" button pressed.
2146 //           Assign filters VTK viewer and close dialog
2147 //=======================================================================
2148 void SMESHGUI_FilterDlg::onOk()
2149 {
2150   if (onApply())
2151   {
2152     mySelectionMgr->clearFilters();
2153     disconnect(mySMESHGUI, 0, this, 0);
2154     disconnect(mySelectionMgr, 0, this, 0);
2155     mySMESHGUI->ResetState();
2156     accept();
2157     emit Accepted();
2158   }
2159 }
2160
2161 //=======================================================================
2162 // name    : SMESHGUI_FilterDlg::onClose
2163 // Purpose : SLOT called when "Close" button pressed. Close dialog
2164 //=======================================================================
2165 void SMESHGUI_FilterDlg::onClose()
2166 {
2167   // Restore previously selected object
2168   if (mySelectionMgr)
2169   {
2170     SALOME_ListIO aList;
2171     mySelectionMgr->clearFilters();
2172     mySelectionMgr->clearSelected();
2173     SALOME_DataMapIteratorOfDataMapOfIOMapOfInteger anIter (myIObjects);
2174     for ( ; anIter.More(); anIter.Next())
2175     {
2176       aList.Append(anIter.Key());
2177
2178       TColStd_MapOfInteger aResMap;
2179       const TColStd_IndexedMapOfInteger& anIndMap = anIter.Value();
2180       for (int i = 1, n = anIndMap.Extent(); i <= n; i++)
2181         aResMap.Add(anIndMap(i));
2182
2183       mySelector->AddOrRemoveIndex( anIter.Key(), aResMap, false);
2184       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
2185         aViewWindow->highlight( anIter.Key(), true, true );
2186     }
2187     mySelectionMgr->setSelectedObjects(aList, false);
2188   }
2189
2190   disconnect(mySMESHGUI, 0, this, 0);
2191   disconnect(mySelectionMgr, 0, this, 0);
2192   mySMESHGUI->ResetState();
2193   reject();
2194   return;
2195 }
2196
2197 //=================================================================================
2198 // function : onHelp()
2199 // purpose  :
2200 //=================================================================================
2201 void SMESHGUI_FilterDlg::onHelp()
2202 {
2203   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
2204   if (app) 
2205     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
2206   else {
2207     QString platform;
2208 #ifdef WIN32
2209     platform = "winapplication";
2210 #else
2211     platform = "application";
2212 #endif
2213     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
2214                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
2215                              arg(app->resourceMgr()->stringValue("ExternalBrowser", 
2216                                                                  platform)).
2217                              arg(myHelpFileName));
2218   }
2219 }
2220
2221 //=======================================================================
2222 // name    : SMESHGUI_FilterDlg::onDeactivate
2223 // Purpose : SLOT called when dialog must be deativated
2224 //=======================================================================
2225 void SMESHGUI_FilterDlg::onDeactivate()
2226 {
2227   setEnabled(false);
2228 }
2229
2230 //=======================================================================
2231 // name    : SMESHGUI_FilterDlg::enterEvent
2232 // Purpose : Event filter
2233 //=======================================================================
2234 void SMESHGUI_FilterDlg::enterEvent (QEvent*)
2235 {
2236 //  mySMESHGUI->EmitSignalDeactivateDialog();
2237   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
2238   mySMESHGUI->ResetState();
2239   setEnabled(true);
2240 }
2241
2242 //=======================================================================
2243 // name    : closeEvent()
2244 // Purpose :
2245 //=======================================================================
2246 void SMESHGUI_FilterDlg::closeEvent (QCloseEvent*)
2247 {
2248   onClose();
2249 }
2250
2251 //=======================================================================
2252 // name    : SMESHGUI_FilterDlg::getIdsFromWg
2253 // Purpose : Retrieve list of ids from given widget
2254 //=======================================================================
2255 void SMESHGUI_FilterDlg::getIdsFromWg (const QWidget* theWg, QList<int>& theRes) const
2256 {
2257   theRes.clear();
2258   if (theWg == 0)
2259     return;
2260
2261   if (theWg->inherits("QListWidget"))
2262   {
2263     const QListWidget* aListBox = qobject_cast<const QListWidget*>( theWg );
2264     bool b;
2265     for (int i = 0, n = aListBox->count(); i < n; i++)
2266     {
2267       int anId = aListBox->item(i)->text().toInt(&b);
2268       if (b)
2269         theRes.append(anId);
2270     }
2271   }
2272   else if (theWg->inherits("QLineEdit"))
2273   {
2274     const QLineEdit* aLineEdit = qobject_cast<const QLineEdit*>( theWg );
2275     QString aStr = aLineEdit->text();
2276     QRegExp aRegExp("(\\d+)");
2277     bool b;
2278     int aPos = 0;
2279     while (aPos >= 0)
2280     {
2281       aPos = aRegExp.indexIn(aStr, aPos);
2282       if (aPos > -1)
2283       {
2284         int anId = aRegExp.cap(1).toInt(&b);
2285         if (b)
2286           theRes.append(anId);
2287         aPos += aRegExp.matchedLength();
2288       }
2289     }
2290   }
2291 }
2292
2293 //=======================================================================
2294 // name    : SMESHGUI_FilterDlg::getSelMode
2295 // Purpose : Get selection mode of specified type
2296 //=======================================================================
2297 Selection_Mode SMESHGUI_FilterDlg::getSelMode (const int theType) const
2298 {
2299   switch (theType)
2300   {
2301     case SMESH::NODE   : return NodeSelection;
2302     case SMESH::EDGE   : return EdgeSelection;
2303     case SMESH::FACE   : return FaceSelection;
2304     case SMESH::VOLUME : return VolumeSelection;
2305     default            : return ActorSelection;
2306   }
2307
2308 }
2309
2310 //=======================================================================
2311 // name    : SMESHGUI_FilterDlg::setIdsToWg
2312 // Purpose : Insert identifiers in specified widgets
2313 //=======================================================================
2314 void SMESHGUI_FilterDlg::setIdsToWg (QWidget* theWg, const QList<int>& theIds)
2315 {
2316   if (theWg == 0)
2317     return;
2318
2319   if (theWg->inherits("QListWidget"))
2320   {
2321     QListWidget* aListBox = qobject_cast<QListWidget*>( theWg );
2322     aListBox->clear();
2323
2324     QStringList aStrList;
2325     QList<int>::const_iterator anIter;
2326     for (anIter = theIds.begin(); anIter != theIds.end(); ++anIter)
2327       aStrList.append(QString("%1").arg(*anIter));
2328
2329     aListBox->addItems(aStrList);
2330   }
2331   else if (theWg->inherits("QLineEdit"))
2332   {
2333     QLineEdit* aLineEdit = qobject_cast<QLineEdit*>( theWg );
2334     QString aStr;
2335     QList<int>::const_iterator anIter;
2336
2337     for (anIter = theIds.begin(); anIter != theIds.end(); ++ anIter)
2338       aStr += QString("%1 ").arg(*anIter);
2339
2340     if (!aStr.isEmpty())
2341       aStr.remove(aStr.length() - 1, 1);
2342
2343     aLineEdit->setText(aStr);
2344   }
2345 }
2346
2347 //=======================================================================
2348 // name    : SMESHGUI_FilterDlg::isValid
2349 // Purpose : Verify validity of input data
2350 //=======================================================================
2351 bool SMESHGUI_FilterDlg::isValid() const
2352 {
2353   if (!myTable->IsValid())
2354     return false;
2355
2356   for (int i = 0, n = myTable->NumRows(); i < n; i++)
2357   {
2358     int aType = myTable->GetCriterionType(i);
2359     if (aType == SMESH::FT_BelongToGeom ||
2360         aType == SMESH::FT_BelongToPlane ||
2361         aType == SMESH::FT_BelongToCylinder ||
2362         aType == SMESH::FT_BelongToGenSurface ||
2363         aType == SMESH::FT_LyingOnGeom) {
2364       QString aName;
2365       myTable->GetThreshold(i, aName);
2366
2367       std::vector<_PTR(SObject)> aList =
2368         SMESH::GetActiveStudyDocument()->FindObjectByName(aName.toLatin1().data(), "GEOM");
2369       if (aList.size() == 0) {
2370         SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"),
2371                                      tr("BAD_SHAPE_NAME").arg(aName));
2372         return false;
2373       }
2374
2375       if (aType == SMESH::FT_BelongToCylinder ||
2376           aType == SMESH::FT_BelongToPlane    ||
2377           aType == SMESH::FT_BelongToGenSurface ) {
2378         CORBA::Object_var anObject = SMESH::SObjectToObject(aList[ 0 ]);
2379         //GEOM::GEOM_Object_var aGeomObj = GEOM::GEOM_Object::_narrow(aList[ 0 ]->GetObject());
2380         GEOM::GEOM_Object_var aGeomObj = GEOM::GEOM_Object::_narrow(anObject);
2381         if (!aGeomObj->_is_nil()) {
2382           TopoDS_Shape aFace;
2383           if (!GEOMBase::GetShape(aGeomObj, aFace) ||
2384                aFace.IsNull() ||
2385                aFace.ShapeType() != TopAbs_FACE) {
2386             SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"),
2387                                          tr("SHAPE_IS_NOT_A_FACE").arg(aName));
2388             return false;
2389           }
2390
2391           Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
2392           if (aSurf.IsNull()) {
2393             SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"),
2394                                          tr("SHAPE_IS_NOT_A_FACE").arg(aName));
2395             return false;
2396           }
2397
2398           if (aType == SMESH::FT_BelongToPlane && !aSurf->IsKind(STANDARD_TYPE(Geom_Plane))) {
2399             SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"),
2400                                          tr("SHAPE_IS_NOT_A_PLANE").arg(aName));
2401             return false;
2402           }
2403
2404           if (aType == SMESH::FT_BelongToCylinder && !aSurf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) {
2405             SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INSUFFICIENT_DATA"),
2406                                          tr("SHAPE_IS_NOT_A_CYLINDER").arg(aName));
2407             return false;
2408           }
2409         }
2410       }
2411     }
2412   }
2413
2414   return true;
2415 }
2416
2417 //=======================================================================
2418 // name    : SMESHGUI_FilterDlg::SetSourceWg
2419 // Purpose : Set widget of parent dialog containing idsto be filtered if
2420 //           user select corresponding source radio button
2421 //=======================================================================
2422 void SMESHGUI_FilterDlg::SetSourceWg (QWidget* theWg)
2423 {
2424   mySourceWg = theWg;
2425 }
2426
2427 //=======================================================================
2428 // name    : SMESHGUI_FilterDlg::SetGroupIds
2429 // Purpose : Set mesh
2430 //=======================================================================
2431 void SMESHGUI_FilterDlg::SetMesh (SMESH::SMESH_Mesh_ptr theMesh)
2432 {
2433   myMesh = theMesh;
2434 }
2435
2436 //=======================================================================
2437 // name    : SMESHGUI_FilterDlg::SetSelection
2438 // Purpose : Get filtered ids
2439 //=======================================================================
2440 void SMESHGUI_FilterDlg::SetSelection()
2441 {
2442   if (mySelectionMgr)
2443     disconnect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(onSelectionDone()));
2444
2445   if (mySelectionMgr) {
2446     myIObjects.Clear();
2447     const SALOME_ListIO& anObjs = mySelector->StoredIObjects();
2448     SALOME_ListIteratorOfListIO anIter (anObjs);
2449     for ( ; anIter.More(); anIter.Next()) {
2450       TColStd_IndexedMapOfInteger aMap;
2451       mySelector->GetIndex(anIter.Value(), aMap);
2452       myIObjects.Bind(anIter.Value(), aMap);
2453     }
2454
2455     connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
2456
2457     updateSelection();
2458   }
2459   else
2460     myIObjects.Clear();
2461 }
2462
2463 //=======================================================================
2464 // name    : SMESHGUI_FilterDlg::onApply
2465 // Purpose : SLOT called when "Apply" button pressed.
2466 //           Assign filters to VTK viewer
2467 //=======================================================================
2468 bool SMESHGUI_FilterDlg::onApply()
2469 {
2470   if (!isValid())
2471     return false;
2472
2473   try {
2474     int aCurrType = myTable->GetType();
2475
2476     if (!createFilter(aCurrType))
2477       return false;
2478
2479     insertFilterInViewer();
2480
2481     if (!myFilter[ aCurrType ]->GetPredicate()->_is_nil()) {
2482       QList<int> aResultIds;
2483       filterSource(aCurrType, aResultIds);
2484       selectInViewer(aCurrType, aResultIds);
2485     }
2486
2487     myInsertState[ aCurrType ] = mySetInViewer->isChecked();
2488     myApplyToState[ aCurrType ] = mySourceGrp->checkedId();
2489   }
2490   catch(const SALOME::SALOME_Exception& S_ex)
2491   {
2492     SalomeApp_Tools::QtCatchCorbaException(S_ex);
2493   }
2494   catch(...)
2495   {
2496   }
2497
2498   return true;
2499 }
2500
2501 //=======================================================================
2502 // name    : SMESHGUI_FilterDlg::createFilter
2503 // Purpose : Create predicate for given type
2504 //=======================================================================
2505 bool SMESHGUI_FilterDlg::createFilter (const int theType)
2506 {
2507   SMESH::FilterManager_var aFilterMgr = SMESH::GetFilterManager();
2508   if (aFilterMgr->_is_nil())
2509     return false;
2510
2511   int n = myTable->NumRows();
2512
2513   SMESH::Filter::Criteria_var aCriteria = new SMESH::Filter::Criteria;
2514   aCriteria->length(n);
2515
2516   long aPrecision = -1;
2517   SUIT_ResourceMgr* mgr = SMESH::GetResourceMgr( mySMESHGUI );
2518
2519   if ( mgr && mgr->booleanValue( "SMESH", "use_precision", false ) )
2520     aPrecision = mgr->integerValue( "SMESH", "controls_precision", aPrecision );
2521
2522   for (CORBA::ULong i = 0; i < n; i++) {
2523     SMESH::Filter::Criterion aCriterion = createCriterion();
2524     myTable->GetCriterion(i, aCriterion);
2525     aCriterion.Precision = aPrecision;
2526     aCriteria[ i ] = aCriterion;
2527   }
2528
2529   myFilter[ theType ] = aFilterMgr->CreateFilter();
2530   myFilter[ theType ]->SetCriteria(aCriteria.inout());
2531
2532   return true;
2533 }
2534
2535 //=======================================================================
2536 // name    : SMESHGUI_FilterDlg::insertFilterInViewer
2537 // Purpose : Insert filter in viewer
2538 //=======================================================================
2539 void SMESHGUI_FilterDlg::insertFilterInViewer()
2540 {
2541   if (SVTK_Selector* aSelector = SMESH::GetSelector()) {
2542     SMESH::ElementType anEntType = (SMESH::ElementType)myTable->GetType();
2543
2544     if (myFilter[ myTable->GetType() ]->_is_nil() ||
2545          myFilter[ myTable->GetType() ]->GetPredicate()->_is_nil() ||
2546          !mySetInViewer->isChecked()) {
2547       SMESH::RemoveFilter(getFilterId(anEntType), aSelector);
2548     }
2549     else {
2550       Handle(SMESHGUI_PredicateFilter) aFilter = new SMESHGUI_PredicateFilter();
2551       aFilter->SetPredicate(myFilter[ myTable->GetType() ]->GetPredicate());
2552       SMESH::RemoveFilter(getFilterId(anEntType), aSelector); //skl for IPAL12631
2553       SMESH::SetFilter(aFilter, aSelector);
2554     }
2555   }
2556 }
2557
2558 //=======================================================================
2559 // name    : SMESHGUI_FilterDlg::filterSource
2560 // Purpose : Filter source ids
2561 //=======================================================================
2562 void SMESHGUI_FilterDlg::filterSource (const int theType,
2563                                        QList<int>& theResIds)
2564 {
2565   theResIds.clear();
2566   if (myFilter[ theType ]->_is_nil())
2567     return;
2568
2569   int aSourceId = mySourceGrp->checkedId();
2570
2571   if (aSourceId == Mesh)
2572   {
2573     if (myMesh->_is_nil())
2574       return;
2575     SMESH::long_array_var anIds = myFilter[ theType ]->GetElementsId(myMesh);
2576     for (int i = 0, n = anIds->length(); i < n; i++)
2577       theResIds.append(anIds[ i ]);
2578   }
2579   else if (aSourceId == Selection)
2580   {
2581     filterSelectionSource(theType, theResIds);
2582   }
2583   else if (aSourceId == Dialog)
2584   {
2585     // retrieve ids from dialog
2586     QList<int> aDialogIds;
2587     getIdsFromWg(mySourceWg, aDialogIds);
2588
2589     if (myMesh->_is_nil())
2590     {
2591       theResIds = aDialogIds;
2592       return;
2593     }
2594
2595     // filter ids
2596     SMESH::Predicate_ptr aPred = myFilter[ theType ]->GetPredicate();
2597     aPred->SetMesh(myMesh);
2598     QList<int>::const_iterator anIter;
2599     for (anIter = aDialogIds.begin(); anIter != aDialogIds.end(); ++ anIter)
2600       if (aPred->IsSatisfy(*anIter))
2601         theResIds.append(*anIter);
2602
2603     // set ids to the dialog
2604     setIdsToWg(mySourceWg, theResIds);
2605   }
2606 }
2607
2608 //=======================================================================
2609 // name    : SMESHGUI_FilterDlg::filterSelectionSource
2610 // Purpose : Filter source selection
2611 //=======================================================================
2612 void SMESHGUI_FilterDlg::filterSelectionSource (const int theType,
2613                                                 QList<int>& theResIds)
2614 {
2615   theResIds.clear();
2616   if (myMesh->_is_nil() || mySelectionMgr == 0)
2617     return;
2618
2619   // Create map of entities to be filtered
2620   TColStd_MapOfInteger aToBeFiltered;
2621   SALOME_DataMapIteratorOfDataMapOfIOMapOfInteger anIter(myIObjects);
2622
2623   for ( ; anIter.More(); anIter.Next())
2624   {
2625     // process sub mesh
2626     SMESH::SMESH_subMesh_var aSubMesh = SMESH::IObjectToInterface<SMESH::SMESH_subMesh>(anIter.Key());
2627     if (!aSubMesh->_is_nil())
2628     {
2629       if (aSubMesh->GetFather()->GetId() == myMesh->GetId())
2630       {
2631         SMESH::long_array_var anIds =
2632           theType == SMESH::NODE ? aSubMesh->GetNodesId() : aSubMesh->GetElementsId();
2633         for (int i = 0, n = anIds->length(); i < n; i++)
2634           aToBeFiltered.Add(anIds[ i ]);
2635       }
2636     }
2637
2638     // process group
2639     SMESH::SMESH_GroupBase_var aGroup =
2640       SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>(anIter.Key());
2641     if (!aGroup->_is_nil())
2642     {
2643       if (aGroup->GetType() == theType && aGroup->GetMesh()->GetId() == myMesh->GetId())
2644       {
2645         SMESH::long_array_var anIds = aGroup->GetListOfID();
2646         for (int i = 0, n = anIds->length(); i < n; i++)
2647           aToBeFiltered.Add(anIds[ i ]);
2648       }
2649     }
2650
2651     // process mesh
2652     SMESH::SMESH_Mesh_var aMeshPtr = SMESH::IObjectToInterface<SMESH::SMESH_Mesh>(anIter.Key());
2653     if (!aMeshPtr->_is_nil() && aMeshPtr->GetId() == myMesh->GetId())
2654     {
2655       const TColStd_IndexedMapOfInteger& aSelMap = anIter.Value();
2656
2657       if (aSelMap.Extent() > 0)
2658       {
2659         if(SMESH::FindActorByEntry(anIter.Key()->getEntry()))
2660         {
2661           for (int i = 1; i <= aSelMap.Extent(); i++)
2662             aToBeFiltered.Add(aSelMap(i));
2663         }
2664       }
2665     }
2666   }
2667
2668   // Filter entities
2669   SMESH::Predicate_ptr aPred = myFilter[ theType ]->GetPredicate();
2670   aPred->SetMesh(myMesh);
2671   TColStd_MapIteratorOfMapOfInteger aResIter(aToBeFiltered);
2672   for ( ; aResIter.More(); aResIter.Next())
2673     if (aPred->IsSatisfy(aResIter.Key()))
2674       theResIds.append(aResIter.Key());
2675 }
2676
2677 //=======================================================================
2678 // name    : SMESHGUI_FilterDlg::selectInViewer
2679 // Purpose : Select given entities in viewer
2680 //=======================================================================
2681 void SMESHGUI_FilterDlg::selectInViewer (const int theType, const QList<int>& theIds)
2682 {
2683   if (mySelectionMgr == 0 || myMesh->_is_nil())
2684     return;
2685
2686   mySelectionMgr->clearFilters();
2687
2688   // Set new selection mode if necessary
2689   Selection_Mode aSelMode = getSelMode(theType);
2690   SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI );
2691   if ( aViewWindow && aViewWindow->SelectionMode()!=aSelMode) {
2692     mySelectionMgr->clearSelected();
2693     mySelectionMgr->clearFilters();
2694     if (aSelMode == NodeSelection)
2695       SMESH::SetPointRepresentation(true);
2696     aViewWindow->SetSelectionMode(aSelMode);
2697   }
2698
2699   // Clear selection
2700   SMESH_Actor* anActor = SMESH::FindActorByObject(myMesh);
2701   if (!anActor || !anActor->hasIO())
2702     return;
2703
2704   Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
2705   //mySelectionMgr->clearSelected();
2706   //mySelectionMgr->AddIObject(anIO, false);
2707   SALOME_ListIO aList;
2708   aList.Append(anIO);
2709   mySelectionMgr->setSelectedObjects(aList, false);
2710
2711   // Remove filter corresponding to the current type from viewer
2712   int aType = myTable->GetType();
2713   int aFilterId = SMESH::UnknownFilter;
2714   if      (aType == SMESH::EDGE  ) aFilterId = SMESH::EdgeFilter;
2715   else if (aType == SMESH::FACE  ) aFilterId = SMESH::FaceFilter;
2716   else if (aType == SMESH::VOLUME) aFilterId = SMESH::VolumeFilter;
2717   Handle(VTKViewer_Filter) aFilter = SMESH::GetFilter(aFilterId);
2718   SMESH::RemoveFilter(aFilterId);
2719
2720   // get vtk ids
2721   TColStd_MapOfInteger aMap;
2722   QList<int>::const_iterator anIter;
2723   for (anIter = theIds.begin(); anIter != theIds.end(); ++anIter) {
2724     aMap.Add(*anIter);
2725   }
2726
2727   // Set new selection
2728   mySelector->AddOrRemoveIndex(anIO, aMap, false);
2729   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
2730     aViewWindow->highlight( anIO, true, true );
2731
2732   // insert previously stored filter in viewer if necessary
2733   if (!aFilter.IsNull())
2734     SMESH::SetFilter(aFilter);
2735 }
2736
2737 //=======================================================================
2738 // name    : SMESHGUI_FilterDlg::createCriterion
2739 // Purpose : Create criterion structure with default values
2740 //=======================================================================
2741 SMESH::Filter::Criterion SMESHGUI_FilterDlg::createCriterion()
2742 {
2743    SMESH::Filter::Criterion aCriterion;
2744
2745   aCriterion.Type          = SMESH::FT_Undefined;
2746   aCriterion.Compare       = SMESH::FT_Undefined;
2747   aCriterion.Threshold     = 0;
2748   aCriterion.UnaryOp       = SMESH::FT_Undefined;
2749   aCriterion.BinaryOp      = SMESH::FT_Undefined;
2750   aCriterion.ThresholdStr  = "";
2751   aCriterion.ThresholdID   = "";
2752   aCriterion.TypeOfElement = SMESH::ALL;
2753
2754   return aCriterion;
2755 }
2756
2757 //=======================================================================
2758 // name    : SMESHGUI_FilterDlg::onSelectionDone
2759 // Purpose : SLOT called when selection changed.
2760 //           If current cell corresponds to the threshold value of
2761 //           BelongToGeom criterion name of selected object is set in this cell
2762 //=======================================================================
2763 void SMESHGUI_FilterDlg::onSelectionDone()
2764 {
2765   int aRow, aCol;
2766   const SALOME_ListIO& aList = mySelector->StoredIObjects();
2767
2768   if (aList.Extent() != 1 ||
2769       !myTable->CurrentCell(aRow, aCol) ||
2770       myTable->GetCriterionType(aRow) != SMESH::FT_BelongToGeom &&
2771       myTable->GetCriterionType(aRow) != SMESH::FT_BelongToPlane &&
2772       myTable->GetCriterionType(aRow) != SMESH::FT_BelongToCylinder &&
2773       myTable->GetCriterionType(aRow) != SMESH::FT_BelongToGenSurface &&
2774       myTable->GetCriterionType(aRow) != SMESH::FT_LyingOnGeom)
2775     return;
2776
2777   Handle(SALOME_InteractiveObject) anIO = aList.First();
2778   GEOM::GEOM_Object_var anObj = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);
2779   if (!anObj->_is_nil())
2780     {
2781       myTable->SetThreshold(aRow, GEOMBase::GetName(anObj));
2782       //myTable->SetID( aRow, GEOMBase::GetIORFromObject(anObj));
2783       myTable->SetID(aRow, anIO->getEntry());
2784     }
2785 }
2786
2787 //=======================================================================
2788 // name    : SMESHGUI_FilterDlg::onCriterionChanged
2789 // Purpose : SLOT called when cretarion of current row changed. Update selection
2790 //=======================================================================
2791 void SMESHGUI_FilterDlg::onCriterionChanged (const int, const int)
2792 {
2793   updateSelection();
2794 }
2795
2796 //=======================================================================
2797 // name    : SMESHGUI_FilterDlg::onCurrentChanged
2798 // Purpose : SLOT called when current row changed. Update selection
2799 //=======================================================================
2800 void SMESHGUI_FilterDlg::onCurrentChanged (int, int)
2801 {
2802   updateSelection();
2803 }
2804
2805 //=======================================================================
2806 // name    : SMESHGUI_FilterDlg::updateSelection
2807 // Purpose : UpdateSelection in accordance with current row
2808 //=======================================================================
2809 void SMESHGUI_FilterDlg::updateSelection()
2810 {
2811   if (mySelectionMgr == 0)
2812     return;
2813
2814   TColStd_MapOfInteger allTypes;
2815   for( int i=0; i<10; i++ )
2816     allTypes.Add( i );
2817   SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>( mySMESHGUI->application()->activeStudy() );
2818   if( !aStudy )
2819     return;
2820
2821
2822   mySelectionMgr->clearFilters();
2823
2824   int aRow, aCol;
2825
2826   if (myTable->CurrentCell(aRow, aCol) &&
2827       (myTable->GetCriterionType(aRow) == SMESH::FT_BelongToGeom ||
2828        myTable->GetCriterionType(aRow) == SMESH::FT_BelongToPlane ||
2829        myTable->GetCriterionType(aRow) == SMESH::FT_BelongToCylinder ||
2830        myTable->GetCriterionType(aRow) == SMESH::FT_BelongToGenSurface ||
2831        myTable->GetCriterionType(aRow) == SMESH::FT_LyingOnGeom)) {
2832
2833     if (myTable->GetCriterionType(aRow) == SMESH::FT_BelongToGeom ||
2834         myTable->GetCriterionType(aRow) == SMESH::FT_BelongToGenSurface ||
2835         myTable->GetCriterionType(aRow) == SMESH::FT_LyingOnGeom) {
2836
2837       mySelectionMgr->installFilter(new GEOM_SelectionFilter( aStudy, true ));
2838
2839     } else if (myTable->GetCriterionType(aRow) == SMESH::FT_BelongToPlane) {
2840       mySelectionMgr->installFilter(new GEOM_FaceFilter( aStudy, StdSelect_Plane ) );
2841
2842     } else if (myTable->GetCriterionType(aRow) == SMESH::FT_BelongToCylinder) {
2843       mySelectionMgr->installFilter(new GEOM_FaceFilter( aStudy, StdSelect_Cylinder ) );
2844     }
2845     myIsSelectionChanged = true;
2846
2847   } else {
2848     if (myIsSelectionChanged) {
2849       mySelectionMgr->installFilter( new GEOM_TypeFilter( aStudy, -1 ) ); // This filter deactivates selection
2850     }
2851   }
2852 }
2853
2854 //=================================================================================
2855 // function : keyPressEvent()
2856 // purpose  :
2857 //=================================================================================
2858 void SMESHGUI_FilterDlg::keyPressEvent( QKeyEvent* e )
2859 {
2860   QDialog::keyPressEvent( e );
2861   if ( e->isAccepted() )
2862     return;
2863
2864   if ( e->key() == Qt::Key_F1 ) {
2865     e->accept();
2866     onHelp();
2867   }
2868 }