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