Salome HOME
Merge remote branch 'origin/V8_5_asterstudy'
[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     myRemoveButton->setEnabled( mySelectedIDs.size() > 0 );
391
392     //Connect Selected Ids in viewer and dialog's Ids list
393     bool signalsBlocked = myListWidget->blockSignals( true );
394     myListWidget->clearSelection();
395     if ( mySelectedIDs.size() > 0 ) {
396       for (int i = 0; i < mySelectedIDs.size(); i++) {
397         QString anID = QString(" %1").arg( mySelectedIDs.at(i) );
398         QList<QListWidgetItem*> anItems = myListWidget->findItems ( anID, Qt::MatchExactly );
399         QListWidgetItem* item;
400         foreach(item, anItems)
401           item->setSelected(true);
402       }
403     }
404     myListWidget->blockSignals( signalsBlocked );
405   }
406
407   emit shapeSelected();
408 }
409
410 //=================================================================================
411 // function : onAdd()
412 // purpose  : Called when Add Button Clicked
413 //=================================================================================
414 void StdMeshersGUI_SubShapeSelectorWdg::onAdd()
415 {
416   if ( mySelectedIDs.size() < 1 || !myListWidget )
417     return;
418
419   myListWidget->blockSignals( true );
420   for (int i = 0; i < mySelectedIDs.size() && (myMaxSize == -1 || myListOfIDs.size() < myMaxSize); i++) {
421     if ( myListOfIDs.indexOf( mySelectedIDs.at(i) ) == -1 ) {
422       QString anID = QString(" %1").arg( mySelectedIDs.at(i) );
423
424       QListWidgetItem* anItem = new QListWidgetItem( anID, myListWidget );
425       anItem->setSelected(true);
426       
427       myListOfIDs.append( mySelectedIDs.at(i) );
428     }
429   }
430   onListSelectionChanged();
431   myListWidget->blockSignals( false );
432
433   mySelectedIDs.clear();
434   myAddButton->setEnabled( false );
435 }
436          
437 //=================================================================================
438 // function : onRemove()
439 // purpose  : Called when Remove Button Clicked
440 //=================================================================================
441 void StdMeshersGUI_SubShapeSelectorWdg::onRemove()
442 {
443   if ( myListWidget->count() < 1 || !myListWidget )
444     return;
445
446   myListWidget->blockSignals( true );
447   QList<QListWidgetItem*> selItems = myListWidget->selectedItems();
448   QListWidgetItem* item;
449   foreach(item, selItems) {
450     QString idStr = item->text();
451     int id = idStr.toInt();
452
453     int index = myListOfIDs.indexOf( id );
454     myListOfIDs.removeAt( index );
455     delete item;
456   }
457
458   onListSelectionChanged();
459   myListWidget->blockSignals( false );
460   
461   myAddButton->setEnabled( !mySelectedIDs.isEmpty() );
462 }
463
464 void StdMeshersGUI_SubShapeSelectorWdg::onPrevious()
465 {
466   if ( myPreviewActor ) {
467     myPreviewActor->previous();
468     if ( myListWidget )
469       myListWidget->clearSelection();
470     updateButtons();
471     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
472       aViewWindow->Repaint();
473   }
474 }
475
476 void StdMeshersGUI_SubShapeSelectorWdg::onNext()
477 {
478   if ( myPreviewActor ) {
479     myPreviewActor->next();
480     if ( myListWidget )
481       myListWidget->clearSelection();
482     updateButtons();
483     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
484       aViewWindow->Repaint();
485   }
486 }
487
488 //=================================================================================
489 // function : onListSelectionChanged()
490 // purpose  : Called when selection in element list is changed
491 //=================================================================================
492 void StdMeshersGUI_SubShapeSelectorWdg::onListSelectionChanged()
493 {
494   if ( !myPreviewActor )
495     return;
496
497   myPreviewActor->HighlightAll( false );
498   QList<QListWidgetItem*> selItems = myListWidget->selectedItems();
499   QListWidgetItem* anItem;
500   foreach(anItem, selItems)
501     myPreviewActor->HighlightID( anItem->text().toInt() );
502
503   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
504     aViewWindow->Repaint();
505
506   // update remove button
507   myRemoveButton->setEnabled( selItems.size() > 0 );
508
509   emit selectionChanged();
510 }
511
512 //=================================================================================
513 // function : setGeomShape
514 // purpose  : Called to set geometry whose sub-shapes are selected
515 //================================================================================
516 void StdMeshersGUI_SubShapeSelectorWdg::SetGeomShapeEntry( const QString& theEntry,
517                                                            const QString& theMainShapeEntry )
518 {
519   if ( !theEntry.isEmpty() || theMainShapeEntry.isEmpty() )
520   {
521     myParamValue = theEntry;
522     myEntry      = theEntry.toStdString();
523     myMainEntry  = theMainShapeEntry.toStdString();
524
525     if ( myMainEntry.empty() ) myMainEntry = myEntry;
526     if ( myEntry.empty() )     myEntry     = myMainEntry;
527     if ( myMainEntry.length() > myEntry.length() &&
528          theMainShapeEntry.startsWith( theEntry ))
529       std::swap( myMainEntry, myEntry );
530
531     myGeomShape = GetTopoDSByEntry( myEntry.c_str() );
532     if ( myEntry == myMainEntry )
533       myMainShape = myGeomShape;
534     else
535       myMainShape = GetTopoDSByEntry( myMainEntry.c_str() );
536     updateState();
537   }
538 }
539
540 //=================================================================================
541 // function : updateState
542 // purpose  : update Widget state
543 //=================================================================================
544 void StdMeshersGUI_SubShapeSelectorWdg::updateState()
545 {
546   bool state = ( !myGeomShape.IsNull() );
547
548   myInfoLabel ->setVisible( false );
549   myPrevButton->setVisible( false );
550   myNextButton->setVisible( false );
551
552   if ( myListWidget )
553   {
554     myListWidget->setEnabled( state );
555     myAddButton->setEnabled( mySelectedIDs.size() > 0 );
556   }
557   if ( state ) {
558     SUIT_OverrideCursor wc;
559     if ( !myPreviewActor )
560       myPreviewActor = new SMESH_PreviewActorsCollection();
561     myPreviewActor->SetSelector( mySelector );
562     myPreviewActor->Init( myGeomShape, myMainShape, mySubShType, myEntry.c_str() );
563     myPreviewActor->SetShown( false );
564     myIsShown = false;
565     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) {
566       myRenderer = aViewWindow->getRenderer();
567       myPreviewActor->AddToRender( myRenderer );
568       aViewWindow->Repaint();
569     }
570     updateButtons();
571   }
572 }
573
574 //=================================================================================
575 // function : GetGeomObjectByEntry
576 // purpose  : Called to get GeomObject
577 //=================================================================================
578 GEOM::GEOM_Object_var StdMeshersGUI_SubShapeSelectorWdg::GetGeomObjectByEntry( const QString& theEntry )
579 {
580   GEOM::GEOM_Object_var aGeomObj;
581   SALOMEDS::SObject_var aSObj = SMESH_Gen_i::getStudyServant()->FindObjectID( theEntry.toUtf8().data() );
582   if (!aSObj->_is_nil() )
583   {
584     CORBA::Object_var obj = aSObj->GetObject();
585     aGeomObj = GEOM::GEOM_Object::_narrow(obj);
586     aSObj->UnRegister();
587   }
588   return aGeomObj._retn();
589 }
590
591 //=================================================================================
592 // function : setObjectByEntry
593 // purpose  : Called to get GeomObject
594 //=================================================================================
595 TopoDS_Shape StdMeshersGUI_SubShapeSelectorWdg::GetTopoDSByEntry( const QString& theEntry )
596 {
597   TopoDS_Shape shape;
598   GEOM::GEOM_Object_var aGeomObj = GetGeomObjectByEntry( theEntry );
599   GEOMBase::GetShape(aGeomObj, shape);
600   return shape;
601 }
602
603 //=================================================================================
604 // function : GetListOfIds
605 // purpose  : Called to get the list of SubShapes IDs
606 //=================================================================================
607 SMESH::long_array_var StdMeshersGUI_SubShapeSelectorWdg::GetListOfIDs()
608 {
609   SMESH::long_array_var anArray = new SMESH::long_array;
610
611   int size = myListOfIDs.size();
612   anArray->length( size );
613   for (int i = 0; i < size; i++)
614     anArray[i] = myListOfIDs.at(i);
615
616   return anArray;
617 }
618
619 //=================================================================================
620 // function : SetListOfIds
621 // purpose  : Called to set the list of SubShapes IDs. Returns false if any ID is invalid
622 //=================================================================================
623 bool StdMeshersGUI_SubShapeSelectorWdg::SetListOfIDs( SMESH::long_array_var theIds)
624 {
625   mySelectedIDs.clear();
626   myListOfIDs.clear();
627   int size = theIds->length();
628   for ( int i = 0; i < size; i++ )
629     mySelectedIDs.append( theIds[ i ] );
630
631   if ( myListWidget )
632   {
633     myListWidget->blockSignals( true );
634     myListWidget->clear();
635     myListWidget->blockSignals( false );
636   }
637
638   bool isOk = true;
639   if ( myPreviewActor )
640   {
641     for ( int i = 0; i < size && isOk; i++ )
642       isOk = myPreviewActor->IsValidIndex( theIds[ i ] );
643   }
644   else if ( !myMainShape.IsNull() )
645   {
646     TopTools_IndexedMapOfShape aMainMap;
647     TopExp::MapShapes(myMainShape, aMainMap);
648     for ( int i = 0; i < size && isOk; i++ )
649       isOk = ( theIds[ i ] > 0 && theIds[ i ] <= aMainMap.Extent() );
650   }
651   onAdd();
652   return isOk;
653 }
654
655 //=================================================================================
656 // function : GetMainShapeEntry
657 // purpose  : Called to get the Main Object Entry
658 //=================================================================================
659 const char* StdMeshersGUI_SubShapeSelectorWdg::GetMainShapeEntry()
660 {
661   if ( myMainEntry.empty() ) myMainEntry = "";
662   return myMainEntry.c_str();
663 }
664
665 void StdMeshersGUI_SubShapeSelectorWdg::updateButtons()
666 {
667   if ( myPreviewActor ) {
668     int total = myPreviewActor->count();
669     int chunk = myPreviewActor->currentChunk();
670     int chunkSize = myPreviewActor->chunkSize();
671     int imin = chunk*chunkSize+1;
672     int imax = std::min((chunk+1)*chunkSize, total);
673     bool vis = imax > 0 && total > chunkSize;
674     myInfoLabel->setVisible( vis );
675     myPrevButton->setVisible( vis );
676     myNextButton->setVisible( vis );
677     myInfoLabel->setText( tr( "X_FROM_Y_ITEMS_SHOWN" ).arg(imin).arg(imax).arg(total) );
678     myPrevButton->setEnabled( myPreviewActor->hasPrevious() );
679     myNextButton->setEnabled( myPreviewActor->hasNext() );
680   }
681 }