Salome HOME
03eeb40826441d93012ab4ab671c4542983a4bb7
[modules/smesh.git] / src / StdMeshersGUI / StdMeshersGUI_SubShapeSelectorWdg.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // File   : StdMeshersGUI_SubShapeSelectorWdg.cxx
21 // Author : Open CASCADE S.A.S. (dmv)
22 // SMESH includes
23 //
24 #include "StdMeshersGUI_SubShapeSelectorWdg.h"
25
26 // SMESH Includes
27 #include "SMESHGUI_Utils.h"
28 #include "SMESHGUI_VTKUtils.h"
29 #include "SMESH_Actor.h"
30 #include "SMESH_Gen_i.hxx"
31 #include "SMESH_LogicalFilter.hxx"
32 #include "SMESH_PreviewActorsCollection.h"
33 #include "SMESH_Type.h"
34
35 // SALOME GUI includes
36 #include <LightApp_SelectionMgr.h>
37 #include <SALOME_ListIO.hxx>
38 #include <SUIT_OverrideCursor.h>
39 #include <SUIT_ResourceMgr.h>
40 #include <SUIT_Session.h>
41 #include <SVTK_Selector.h>
42 #include <SVTK_ViewModel.h>
43 #include <SVTK_ViewWindow.h>
44
45 // GEOM Includes
46 #include <GEOMBase.h>
47 #include <GEOM_TypeFilter.h>
48 #include <GEOM_CompoundFilter.h>
49
50 // Qt includes
51 #include <QPushButton>
52 #include <QGridLayout>
53 #include <QListWidget>
54 #include <QCheckBox>
55 #include <QLineEdit>
56
57 // OCCT includes
58 #include <TColStd_MapOfInteger.hxx>
59 #include <TopoDS_Shape.hxx>
60 #include <TopExp.hxx>
61 #include <TopExp_Explorer.hxx>
62
63
64 #define SPACING 6
65 #define MARGIN 0
66
67 //================================================================================
68 /*!
69  *  Constructor
70  */
71 //================================================================================
72
73 StdMeshersGUI_SubShapeSelectorWdg
74 ::StdMeshersGUI_SubShapeSelectorWdg( QWidget *        parent,
75                                      TopAbs_ShapeEnum subShType,
76                                      const bool       toShowList,
77                                      const bool       toShowActivateBtn ):
78   QWidget( parent ),
79   myMaxSize( -1 ),
80   myPreviewActor( 0 )
81 {
82   QPixmap image0( SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap( "SMESH", tr( "ICON_SELECT" ) ) );
83
84   QGridLayout* layout = new QGridLayout( this );
85   layout->setMargin( MARGIN );
86   layout->setSpacing( SPACING );
87
88   if ( toShowList )
89   {
90     QPixmap iconSelect (SUIT_Session::session()->resourceMgr()->loadPixmap("SMESH", tr("ICON_SELECT")));
91     myListWidget     = new QListWidget( this );
92     myActivateButton = new QPushButton( iconSelect, "", this );
93     myAddButton      = new QPushButton( tr( "SMESH_BUT_ADD" ),    this );
94     myRemoveButton   = new QPushButton( tr( "SMESH_BUT_REMOVE" ), this );
95     myListWidget->setSelectionMode( QListWidget::ExtendedSelection );
96     myListWidget->setMinimumWidth(300);
97     myListWidget->setWrapping(true);
98     myActivateButton->setCheckable( true );
99   }
100   else
101   {
102     myListWidget     = 0;
103     myActivateButton = 0;
104     myAddButton      = 0;
105     myRemoveButton   = 0;
106   }
107   myInfoLabel    = new QLabel( this );
108   myPrevButton   = new QPushButton( "<<", this );
109   myNextButton   = new QPushButton( ">>", this );
110
111   if ( myListWidget )
112   {
113     int row = 0;
114     layout->addWidget(myListWidget,   row, 0, 3+toShowActivateBtn, 3);
115     if ( toShowActivateBtn )
116       layout->addWidget( myActivateButton, row++, 3 );
117     else
118       myActivateButton->hide();
119     layout->addWidget(myAddButton,      row, 3);
120     layout->addWidget(myRemoveButton, ++row, 3);
121     ++row;
122     layout->addWidget(myInfoLabel,    ++row, 0, 1, 3);
123     layout->addWidget(myPrevButton,   ++row, 0);
124     layout->addWidget(myNextButton,     row, 2);
125
126     layout->setRowStretch(row-2, 5);
127     layout->setColumnStretch(1, 5);
128   }
129   else // show only Prev and Next buttons
130   {
131     layout->addWidget(myInfoLabel,    0, 0, 1, 2);
132     layout->addWidget(myPrevButton,   1, 0);
133     layout->addWidget(myNextButton,   1, 1);
134   }
135   //myInfoLabel->setMinimumWidth(300);
136   //myInfoLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
137   myInfoLabel->setAlignment(Qt::AlignCenter);
138
139   mySubShType = subShType;
140
141   init();
142 }
143
144 //================================================================================
145 /*!
146  *  Destructor
147  */
148 //================================================================================
149
150 StdMeshersGUI_SubShapeSelectorWdg::~StdMeshersGUI_SubShapeSelectorWdg()
151 {
152   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) {
153     if ( myPreviewActor ) {
154       myPreviewActor->RemoveFromRender( myRenderer );
155       aViewWindow->Repaint();
156
157       delete myPreviewActor;
158       myPreviewActor = 0;
159     }
160   }
161   myEntry = "";
162   myParamValue = "";
163   myMainShape.Nullify();
164
165   if ( mySelectionMgr && myFilter )
166     mySelectionMgr->removeFilter( myFilter );
167   delete myFilter; myFilter=0;
168
169   mySelectionMgr->clearSelected();
170
171   SUIT_SelectionFilter* filter;
172   foreach( filter, myGeomFilters )
173     delete filter;
174 }
175
176 //================================================================================
177 /*!
178  *  Create a layout, initialize fields
179  */
180 //================================================================================
181
182 void StdMeshersGUI_SubShapeSelectorWdg::init()
183 {
184   myParamValue = "";
185   myListOfIDs.clear();
186   mySelectedIDs.clear();
187
188   mySMESHGUI     = SMESHGUI::GetSMESHGUI();
189   mySelectionMgr = SMESH::GetSelectionMgr( mySMESHGUI );
190   mySelector     = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
191
192   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
193     aViewWindow->SetSelectionMode( ActorSelection );
194
195   myFilter=0;
196
197   if ( myListWidget )
198   {
199     myAddButton->setEnabled( false );
200     myRemoveButton->setEnabled( false );
201
202     connect( myListWidget,   SIGNAL(itemSelectionChanged()),    this, SLOT(onListSelectionChanged()));
203     connect( myActivateButton, SIGNAL( toggled(bool) ), SLOT( ActivateSelection(bool)));
204     connect( myAddButton,    SIGNAL(clicked()), SLOT(onAdd()));
205     connect( myRemoveButton, SIGNAL(clicked()), SLOT(onRemove()));
206   }
207   connect( myPrevButton,   SIGNAL(clicked()), SLOT(onPrevious()));
208   connect( myNextButton,   SIGNAL(clicked()), SLOT(onNext()));
209
210   connect( mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(selectionIntoArgument()));
211
212   updateState();
213 }
214
215 //================================================================================
216 /*!
217  * \brief Install filters to select sub-shapes of mySubShType or their groups
218  */
219 //================================================================================
220
221 void StdMeshersGUI_SubShapeSelectorWdg::setFilter()
222 {
223   // if ( !myFilter )
224   // {
225   //   SalomeApp_Study* study = mySMESHGUI->activeStudy();
226   //   GEOM_TypeFilter* typeFilter = new GEOM_TypeFilter(study, mySubShType, /*isShapeType=*/true );
227   //   GEOM_CompoundFilter* gpoupFilter = new GEOM_CompoundFilter(study);
228   //   gpoupFilter->addSubType( mySubShType );
229   //   myGeomFilters.append( typeFilter );
230   //   myGeomFilters.append( gpoupFilter );
231   //   myFilter = new SMESH_LogicalFilter( myGeomFilters, SMESH_LogicalFilter::LO_OR );
232   // }
233   // mySelectionMgr->installFilter( myFilter );
234 }
235
236 //================================================================================
237 /*!
238  *  Create a layout, initialize fields
239  */
240 //================================================================================
241
242 void StdMeshersGUI_SubShapeSelectorWdg::ShowPreview( bool visible)
243 {
244   if ( !myPreviewActor )
245     return;
246
247   if ( myIsShown != visible ) {
248     myPreviewActor->SetShown( visible );
249     
250     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
251       aViewWindow->Repaint();
252
253     myIsShown = visible;
254   }
255 }
256
257 //================================================================================
258 /*!
259  * \brief Connect/disconnect to change of selection
260  */
261 //================================================================================
262
263 void StdMeshersGUI_SubShapeSelectorWdg::ActivateSelection( bool toActivate )
264 {
265   // adjust state of myActivateButton
266   if ( myActivateButton &&
267        myActivateButton != sender() &&
268        myActivateButton->isChecked() != toActivate )
269   {
270     myActivateButton->toggle();
271     return;
272   }
273
274   if ( !mySelectionMgr ) return;
275
276   if ( toActivate )
277   {
278     connect( mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(selectionIntoArgument()));
279   }
280   else
281   {
282     disconnect(mySelectionMgr, 0, this, 0 );
283   }
284
285   if ( sender() == myActivateButton )
286     ShowPreview( toActivate );
287 }
288
289 //================================================================================
290 /*!
291  * \brief Clears selected IDs. This is a workaround of a bug that
292  *        SUIT_SelectionMgr::clearSelected() does not emit currentSelectionChanged
293  */
294 //================================================================================
295
296 void StdMeshersGUI_SubShapeSelectorWdg::ClearSelected()
297 {
298   mySelectedIDs.clear();
299   selectionIntoArgument();
300 }
301
302 //=================================================================================
303 // function : selectionIntoArgument()
304 // purpose  : Called when selection has changed or in other cases
305 //=================================================================================
306 void StdMeshersGUI_SubShapeSelectorWdg::selectionIntoArgument()
307 {
308   if ( !myPreviewActor )
309     return;
310
311   mySelectedIDs.clear();
312
313   // get selected mesh
314   SALOME_ListIO aList;
315   mySelectionMgr->selectedObjects( aList );
316   int nbSel = aList.Extent();
317
318   if (nbSel > 0) {
319     SALOME_ListIteratorOfListIO anIt (aList);
320
321     for ( ; anIt.More(); anIt.Next()) // Loop on selected objects
322     {
323       Handle(SALOME_InteractiveObject) IO = anIt.Value();
324
325       GEOM::GEOM_Object_var aGeomObj = GetGeomObjectByEntry( IO->getEntry() );
326       if ( !CORBA::is_nil( aGeomObj ) ) { // Selected Object From Study
327         // commented for IPAL52836
328         //
329         // GEOM::GEOM_Object_var aGeomFatherObj = aGeomObj->GetMainShape();
330         // QString aFatherEntry = "";
331         // QString aMainFatherEntry = "";
332         // TopoDS_Shape shape;
333         // if ( !CORBA::is_nil( aGeomFatherObj ) ) {
334         //   // Get Main Shape
335         //   GEOM::GEOM_Object_var aGeomMain = GetGeomObjectByEntry( myEntry.c_str() );
336         //   if ( !CORBA::is_nil( aGeomMain ) && aGeomMain->GetType() == 37 ) {  // Main Shape is a Group
337         //     GEOM::GEOM_Object_var aMainFatherObj = aGeomMain->GetMainShape();
338         //     if ( !CORBA::is_nil( aMainFatherObj ) )
339         //       aMainFatherEntry = aMainFatherObj->GetStudyEntry();
340         //   }
341         //   aFatherEntry = aGeomFatherObj->GetStudyEntry();
342         // }
343
344         // if (( ! aFatherEntry.isEmpty() ) &&
345         //     ( aFatherEntry == myEntry.c_str() || aFatherEntry == aMainFatherEntry ) )
346         {
347           TopoDS_Shape shape;
348           if ( aGeomObj->GetType() == 37 /*GEOM_GROUP*/ ) { // Selected Group that belongs the main object
349             GEOMBase::GetShape(aGeomObj, shape);
350             if ( !shape.IsNull() ) {
351               TopExp_Explorer exp( shape, mySubShType );
352               for ( ; exp.More(); exp.Next() ) {
353                 int index = myPreviewActor->GetIndexByShape( exp.Current() );
354                 if ( index ) {
355                   mySelectedIDs.append( index );
356                   myPreviewActor->HighlightID( index );
357                 }
358               }
359             }
360           } else if ( aGeomObj->GetType() == 28 /*GEOM_SUBSHAPE*/ ||
361                       myEntry == IO->getEntry() )
362           {
363             GEOMBase::GetShape(aGeomObj, shape);
364             if ( !shape.IsNull() && shape.ShapeType() == mySubShType ) {
365               int index = myPreviewActor->GetIndexByShape( shape );
366               if ( index ) {
367                 mySelectedIDs.append( index );
368                 myPreviewActor->HighlightID( index );
369               }
370             }
371           }
372         }
373       } else { // Selected Actor from Actor Collection
374         QString anEntry = IO->getEntry();
375         QString str = "_";
376         int index = anEntry.lastIndexOf( str );
377         anEntry.remove(0, index+1);
378         int ind = anEntry.toInt();
379         if ( ind )
380           mySelectedIDs.append( ind );
381       }
382     }
383   }
384   // update add button
385   if ( myListWidget )
386   {
387     myAddButton->setEnabled(( myListWidget->count() < myMaxSize || myMaxSize == -1 ) &&
388                             ( mySelectedIDs.size() > 0                             ) &&
389                             ( mySelectedIDs.size() <= myMaxSize || myMaxSize == -1 ) );
390
391     //Connect Selected Ids in viewer and dialog's Ids list
392     bool signalsBlocked = myListWidget->blockSignals( true );
393     myListWidget->clearSelection();
394     if ( mySelectedIDs.size() > 0 ) {
395       for (int i = 0; i < mySelectedIDs.size(); i++) {
396         QString anID = QString(" %1").arg( mySelectedIDs.at(i) );
397         QList<QListWidgetItem*> anItems = myListWidget->findItems ( anID, Qt::MatchExactly );
398         QListWidgetItem* item;
399         foreach(item, anItems)
400           item->setSelected(true);
401       }
402     }
403     myListWidget->blockSignals( signalsBlocked );
404   }
405
406   emit shapeSelected();
407 }
408
409 //=================================================================================
410 // function : onAdd()
411 // purpose  : Called when Add Button Clicked
412 //=================================================================================
413 void StdMeshersGUI_SubShapeSelectorWdg::onAdd()
414 {
415   if ( mySelectedIDs.size() < 1 || !myListWidget )
416     return;
417
418   myListWidget->blockSignals( true );
419   for (int i = 0; i < mySelectedIDs.size() && (myMaxSize == -1 || myListOfIDs.size() < myMaxSize); i++) {
420     if ( myListOfIDs.indexOf( mySelectedIDs.at(i) ) == -1 ) {
421       QString anID = QString(" %1").arg( mySelectedIDs.at(i) );
422
423       QListWidgetItem* anItem = new QListWidgetItem( anID, myListWidget );
424       anItem->setSelected(true);
425       
426       myListOfIDs.append( mySelectedIDs.at(i) );
427     }
428   }
429   onListSelectionChanged();
430   myListWidget->blockSignals( false );
431
432   mySelectedIDs.clear();
433   myAddButton->setEnabled( false );
434 }
435          
436 //=================================================================================
437 // function : onRemove()
438 // purpose  : Called when Remove Button Clicked
439 //=================================================================================
440 void StdMeshersGUI_SubShapeSelectorWdg::onRemove()
441 {
442   if ( myListWidget->count() < 1 || !myListWidget )
443     return;
444
445   myListWidget->blockSignals( true );
446   QList<QListWidgetItem*> selItems = myListWidget->selectedItems();
447   QListWidgetItem* item;
448   foreach(item, selItems) {
449     QString idStr = item->text();
450     int id = idStr.toInt();
451
452     int index = myListOfIDs.indexOf( id );
453     myListOfIDs.removeAt( index );
454     delete item;
455   }
456
457   onListSelectionChanged();
458   myListWidget->blockSignals( false );
459   
460   myAddButton->setEnabled( !mySelectedIDs.isEmpty() );
461 }
462
463 void StdMeshersGUI_SubShapeSelectorWdg::onPrevious()
464 {
465   if ( myPreviewActor ) {
466     myPreviewActor->previous();
467     if ( myListWidget )
468       myListWidget->clearSelection();
469     updateButtons();
470     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
471       aViewWindow->Repaint();
472   }
473 }
474
475 void StdMeshersGUI_SubShapeSelectorWdg::onNext()
476 {
477   if ( myPreviewActor ) {
478     myPreviewActor->next();
479     if ( myListWidget )
480       myListWidget->clearSelection();
481     updateButtons();
482     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
483       aViewWindow->Repaint();
484   }
485 }
486
487 //=================================================================================
488 // function : onListSelectionChanged()
489 // purpose  : Called when selection in element list is changed
490 //=================================================================================
491 void StdMeshersGUI_SubShapeSelectorWdg::onListSelectionChanged()
492 {
493   if ( !myPreviewActor )
494     return;
495
496   myPreviewActor->HighlightAll( false );
497   QList<QListWidgetItem*> selItems = myListWidget->selectedItems();
498   QListWidgetItem* anItem;
499   foreach(anItem, selItems)
500     myPreviewActor->HighlightID( anItem->text().toInt() );
501
502   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
503     aViewWindow->Repaint();
504
505   // update remove button
506   myRemoveButton->setEnabled( selItems.size() > 0 );
507
508   emit selectionChanged();
509 }
510
511 //=================================================================================
512 // function : setGeomShape
513 // purpose  : Called to set geometry whose sub-shapes are selected
514 //================================================================================
515 void StdMeshersGUI_SubShapeSelectorWdg::SetGeomShapeEntry( const QString& theEntry,
516                                                            const QString& theMainShapeEntry )
517 {
518   if ( !theEntry.isEmpty() || theMainShapeEntry.isEmpty() )
519   {
520     myParamValue = theEntry;
521     myEntry      = theEntry.toStdString();
522     myMainEntry  = theMainShapeEntry.toStdString();
523
524     if ( myMainEntry.empty() ) myMainEntry = myEntry;
525     if ( myEntry.empty() )     myEntry     = myMainEntry;
526     if ( myMainEntry.length() > myEntry.length() &&
527          theMainShapeEntry.startsWith( theEntry ))
528       std::swap( myMainEntry, myEntry );
529
530     myGeomShape = GetTopoDSByEntry( myEntry.c_str() );
531     if ( myEntry == myMainEntry )
532       myMainShape = myGeomShape;
533     else
534       myMainShape = GetTopoDSByEntry( myMainEntry.c_str() );
535     updateState();
536   }
537 }
538
539 //=================================================================================
540 // function : updateState
541 // purpose  : update Widget state
542 //=================================================================================
543 void StdMeshersGUI_SubShapeSelectorWdg::updateState()
544 {
545   bool state = ( !myGeomShape.IsNull() );
546
547   myInfoLabel ->setVisible( false );
548   myPrevButton->setVisible( false );
549   myNextButton->setVisible( false );
550
551   if ( myListWidget )
552   {
553     myListWidget->setEnabled( state );
554     myAddButton->setEnabled( mySelectedIDs.size() > 0 );
555   }
556   if ( state ) {
557     SUIT_OverrideCursor wc;
558     if ( !myPreviewActor )
559       myPreviewActor = new SMESH_PreviewActorsCollection();
560     myPreviewActor->SetSelector( mySelector );
561     myPreviewActor->Init( myGeomShape, myMainShape, mySubShType, myEntry.c_str() );
562     myPreviewActor->SetShown( false );
563     myIsShown = false;
564     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) {
565       myRenderer = aViewWindow->getRenderer();
566       myPreviewActor->AddToRender( myRenderer );
567       aViewWindow->Repaint();
568     }
569     updateButtons();
570   }
571 }
572
573 //=================================================================================
574 // function : GetGeomObjectByEntry
575 // purpose  : Called to get GeomObject
576 //=================================================================================
577 GEOM::GEOM_Object_var StdMeshersGUI_SubShapeSelectorWdg::GetGeomObjectByEntry( const QString& theEntry )
578 {
579   GEOM::GEOM_Object_var aGeomObj;
580   SALOMEDS::Study_var aStudy = SMESHGUI::GetSMESHGen()->GetCurrentStudy();
581   if ( !aStudy->_is_nil() )
582   {
583     SALOMEDS::SObject_var aSObj = aStudy->FindObjectID( theEntry.toLatin1().data() );
584     if (!aSObj->_is_nil() )
585     {
586       CORBA::Object_var obj = aSObj->GetObject();
587       aGeomObj = GEOM::GEOM_Object::_narrow(obj);
588       aSObj->UnRegister();
589     }
590   }
591   return aGeomObj._retn();
592 }
593
594 //=================================================================================
595 // function : setObjectByEntry
596 // purpose  : Called to get GeomObject
597 //=================================================================================
598 TopoDS_Shape StdMeshersGUI_SubShapeSelectorWdg::GetTopoDSByEntry( const QString& theEntry )
599 {
600   TopoDS_Shape shape;
601   GEOM::GEOM_Object_var aGeomObj = GetGeomObjectByEntry( theEntry );
602   GEOMBase::GetShape(aGeomObj, shape);
603   return shape;
604 }
605
606 //=================================================================================
607 // function : GetListOfIds
608 // purpose  : Called to get the list of SubShapes IDs
609 //=================================================================================
610 SMESH::long_array_var StdMeshersGUI_SubShapeSelectorWdg::GetListOfIDs()
611 {
612   SMESH::long_array_var anArray = new SMESH::long_array;
613
614   int size = myListOfIDs.size();
615   anArray->length( size );
616   for (int i = 0; i < size; i++)
617     anArray[i] = myListOfIDs.at(i);
618
619   return anArray;
620 }
621
622 //=================================================================================
623 // function : SetListOfIds
624 // purpose  : Called to set the list of SubShapes IDs. Returns false if any ID is invalid
625 //=================================================================================
626 bool StdMeshersGUI_SubShapeSelectorWdg::SetListOfIDs( SMESH::long_array_var theIds)
627 {
628   mySelectedIDs.clear();
629   myListOfIDs.clear();
630   int size = theIds->length();
631   for ( int i = 0; i < size; i++ )
632     mySelectedIDs.append( theIds[ i ] );
633
634   if ( myListWidget )
635   {
636     myListWidget->blockSignals( true );
637     myListWidget->clear();
638     myListWidget->blockSignals( false );
639   }
640
641   bool isOk = true;
642   if ( myPreviewActor )
643   {
644     for ( int i = 0; i < size && isOk; i++ )
645       isOk = myPreviewActor->IsValidIndex( theIds[ i ] );
646   }
647   else if ( !myMainShape.IsNull() )
648   {
649     TopTools_IndexedMapOfShape aMainMap;
650     TopExp::MapShapes(myMainShape, aMainMap);
651     for ( int i = 0; i < size && isOk; i++ )
652       isOk = ( theIds[ i ] > 0 && theIds[ i ] <= aMainMap.Extent() );
653   }
654   onAdd();
655   return isOk;
656 }
657
658 //=================================================================================
659 // function : GetMainShapeEntry
660 // purpose  : Called to get the Main Object Entry
661 //=================================================================================
662 const char* StdMeshersGUI_SubShapeSelectorWdg::GetMainShapeEntry()
663 {
664   if ( myMainEntry.empty() ) myMainEntry = "";
665   return myMainEntry.c_str();
666 }
667
668 void StdMeshersGUI_SubShapeSelectorWdg::updateButtons()
669 {
670   if ( myPreviewActor ) {
671     int total = myPreviewActor->count();
672     int chunk = myPreviewActor->currentChunk();
673     int chunkSize = myPreviewActor->chunkSize();
674     int imin = chunk*chunkSize+1;
675     int imax = std::min((chunk+1)*chunkSize, total);
676     bool vis = imax > 0 && total > chunkSize;
677     myInfoLabel->setVisible( vis );
678     myPrevButton->setVisible( vis );
679     myNextButton->setVisible( vis );
680     myInfoLabel->setText( tr( "X_FROM_Y_ITEMS_SHOWN" ).arg(imin).arg(imax).arg(total) );
681     myPrevButton->setEnabled( myPreviewActor->hasPrevious() );
682     myNextButton->setEnabled( myPreviewActor->hasNext() );
683   }
684 }