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