Salome HOME
Fix PAL7864 : Impossible to change orientation for group of volumes.
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MultiEditDlg.cxx
1 //  SMESH SMESHGUI : GUI for SMESH component
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SMESHGUI_MultiEditDlg.cxx
25 //  Author : Sergey LITONIN
26 //  Module : SMESH
27
28 #include "SMESHGUI_MultiEditDlg.h"
29 #include "SMESHGUI_FilterDlg.h"
30 #include "SMESHGUI_Filter.h"
31
32 #include "SMESHGUI.h"
33 #include "SMESHGUI_Utils.h"
34 #include "SMESHGUI_VTKUtils.h"
35 #include "SMESHGUI_MeshUtils.h"
36
37 #include "QAD_Desktop.h"
38 #include "QAD_RightFrame.h"
39
40 #include "VTKViewer_ViewFrame.h"
41
42 #include "SMESH_Actor.h"
43 #include "SMDS_Mesh.hxx"
44 #include "SMDS_MeshElement.hxx"
45
46 #include "SALOME_Selection.h"
47 #include "SALOME_ListIteratorOfListIO.hxx"
48 #include "VTKViewer_InteractorStyleSALOME.h"
49
50 #include <vtkCell3D.h>
51 #include <vtkQuad.h>
52 #include <vtkTriangle.h>
53 #include <vtkIdList.h>
54 #include <vtkIntArray.h>
55 #include <vtkCellArray.h>
56 #include <vtkUnsignedCharArray.h>
57 #include <vtkUnstructuredGrid.h>
58 #include <vtkDataSetMapper.h>
59
60 #include <TColStd_IndexedMapOfInteger.hxx>
61 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
62 #include <Precision.hxx>
63 #include <TColStd_DataMapOfIntegerInteger.hxx>
64
65 #include <qcheckbox.h>
66 #include <qframe.h>
67 #include <qgroupbox.h>
68 #include <qlabel.h>
69 #include <qlayout.h>
70 #include <qlineedit.h>
71 #include <qlistbox.h>
72 #include <qpushbutton.h>
73 #include <qapplication.h>
74 #include <qhbuttongroup.h>
75 #include <qradiobutton.h>
76
77 // IDL Headers
78 #include "SALOMEconfig.h"
79 #include CORBA_SERVER_HEADER(SMESH_Group)
80
81 #define SPACING 5
82 #define MARGIN  10
83
84 /*
85   Class       : SMESHGUI_MultiEditDlg
86   Description : Description : Inversion of the diagonal of a pseudo-quadrangle formed by 
87                 2 neighboring triangles with 1 common edge
88 */
89
90 //=======================================================================
91 // name    : SMESHGUI_MultiEditDlg::SMESHGUI_MultiEditDlg
92 // Purpose : Constructor
93 //=======================================================================
94 SMESHGUI_MultiEditDlg::SMESHGUI_MultiEditDlg( QWidget*              theParent, 
95                                               SALOME_Selection*     theSelection,
96                                               const int             theMode,
97                                               const bool            the3d2d,
98                                               const char*           theName )
99 : QDialog( theParent, theName, false, 
100            WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu )
101 {
102   myFilterDlg = 0;
103   mySubmeshFilter = new SMESH_TypeFilter( SUBMESH );
104   myGroupFilter = new SMESH_TypeFilter( GROUP );
105
106   myEntityType = 0;
107
108   myFilterType = theMode;
109   QVBoxLayout* aDlgLay = new QVBoxLayout( this, MARGIN, SPACING );
110
111   QFrame* aMainFrame = createMainFrame  ( this, the3d2d );
112   QFrame* aBtnFrame  = createButtonFrame( this );
113
114   aDlgLay->addWidget( aMainFrame );
115   aDlgLay->addWidget( aBtnFrame );
116
117   aDlgLay->setStretchFactor( aMainFrame, 1 );
118   aDlgLay->setStretchFactor( aBtnFrame, 0 );
119   Init( theSelection ) ;
120 }
121
122 //=======================================================================
123 // name    : SMESHGUI_MultiEditDlg::createMainFrame
124 // Purpose : Create frame containing dialog's input fields
125 //=======================================================================
126 QFrame* SMESHGUI_MultiEditDlg::createMainFrame( QWidget* theParent, const bool the3d2d )
127 {
128   QGroupBox* aMainGrp = new QGroupBox( 1, Qt::Horizontal, theParent );
129   aMainGrp->setFrameStyle( QFrame::NoFrame );
130   aMainGrp->setInsideMargin( 0 );
131
132   QPixmap aPix( QAD_Desktop::getResourceManager()->loadPixmap( "SMESH",tr( "ICON_SELECT" ) ) );
133   
134   // "Selected cells" group
135   mySelGrp = new QGroupBox( 1, Qt::Horizontal,  aMainGrp );
136
137   myEntityTypeGrp = 0;
138   if ( the3d2d ) {
139     myEntityTypeGrp = new QHButtonGroup( tr("SMESH_ELEMENTS_TYPE"), mySelGrp );
140     (new QRadioButton( tr("SMESH_FACE"),   myEntityTypeGrp ))->setChecked( true );
141     (new QRadioButton( tr("SMESH_VOLUME"), myEntityTypeGrp ));
142     myEntityType = myEntityTypeGrp->id( myEntityTypeGrp->selected() );
143   }
144
145   QFrame* aFrame = new QFrame( mySelGrp );
146   
147   myListBox = new QListBox( aFrame );
148   myListBox->setSelectionMode( QListBox::Extended );
149   myListBox->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding) );
150 //  myListBox->setColumnMode( QListBox::FitToHeight );
151   
152   myFilterBtn = new QPushButton( tr( "FILTER" )   , aFrame );
153   myAddBtn    = new QPushButton( tr( "ADD" )      , aFrame );
154   myRemoveBtn = new QPushButton( tr( "REMOVE" )   , aFrame );
155   mySortBtn   = new QPushButton( tr( "SORT_LIST" ), aFrame );
156
157   QGridLayout* aLay = new QGridLayout( aFrame, 5, 2, 0, 5 );
158   aLay->addMultiCellWidget( myListBox, 0, 4, 0, 0 );
159   aLay->addWidget( myFilterBtn, 0, 1 );
160   aLay->addWidget( myAddBtn, 1, 1 );
161   aLay->addWidget( myRemoveBtn, 2, 1 );
162   aLay->addWidget( mySortBtn, 3, 1 );
163   
164   QSpacerItem* aSpacer = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding );
165   aLay->addItem( aSpacer, 4, 1 );
166   
167   myToAllChk = new QCheckBox( tr( "TO_ALL" ), mySelGrp );
168
169   // "Select from" group
170   QGroupBox* aGrp = new QGroupBox( 3, Qt::Horizontal, tr( "SELECT_FROM" ), aMainGrp );
171   
172   mySubmeshChk = new QCheckBox( tr( "SMESH_SUBMESH" ), aGrp );
173   mySubmeshBtn = new QPushButton( aGrp );
174   mySubmesh = new QLineEdit( aGrp );
175   mySubmesh->setReadOnly( true );
176   mySubmeshBtn->setPixmap( aPix );
177   
178   myGroupChk = new QCheckBox( tr( "GROUP" ), aGrp );
179   myGroupBtn = new QPushButton( aGrp );
180   myGroup = new QLineEdit( aGrp );
181   myGroup->setReadOnly( true );
182   myGroupBtn->setPixmap( aPix );
183
184   return aMainGrp;
185 }
186
187 //=======================================================================
188 // name    : SMESHGUI_MultiEditDlg::createButtonFrame
189 // Purpose : Create frame containing buttons
190 //=======================================================================
191 QFrame* SMESHGUI_MultiEditDlg::createButtonFrame( QWidget* theParent )
192 {
193   QFrame* aFrame = new QFrame( theParent );
194   aFrame->setFrameStyle( QFrame::Box | QFrame::Sunken );
195
196   myOkBtn     = new QPushButton( tr( "SMESH_BUT_OK"    ), aFrame );
197   myApplyBtn  = new QPushButton( tr( "SMESH_BUT_APPLY" ), aFrame );
198   myCloseBtn  = new QPushButton( tr( "SMESH_BUT_CLOSE" ), aFrame );
199
200   QSpacerItem* aSpacer = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
201
202   QHBoxLayout* aLay = new QHBoxLayout( aFrame, MARGIN, SPACING );
203
204   aLay->addWidget( myOkBtn );
205   aLay->addWidget( myApplyBtn );
206   aLay->addItem( aSpacer);
207   aLay->addWidget( myCloseBtn );
208
209   return aFrame;
210 }
211
212 //=======================================================================
213 // name    : SMESHGUI_MultiEditDlg::isValid
214 // Purpose : Verify validity of input data
215 //=======================================================================
216 bool SMESHGUI_MultiEditDlg::isValid( const bool /*theMess*/ ) const
217 {
218   return (!myMesh->_is_nil() &&
219           (myListBox->count() > 0 || (myToAllChk->isChecked() && myActor)));
220 }
221
222 //=======================================================================
223 // name    : SMESHGUI_MultiEditDlg::~SMESHGUI_MultiEditDlg
224 // Purpose : Destructor
225 //=======================================================================
226 SMESHGUI_MultiEditDlg::~SMESHGUI_MultiEditDlg()
227 {
228   if ( myFilterDlg != 0 )
229   {
230     myFilterDlg->reparent( 0, QPoint() );
231     delete myFilterDlg;
232   }
233 }
234
235 //=======================================================================
236 // name    : SMESHGUI_MultiEditDlg::Init
237 // Purpose : Init dialog fields, connect signals and slots, show dialog
238 //=======================================================================
239 void SMESHGUI_MultiEditDlg::Init( SALOME_Selection* theSelection )
240 {
241   SMESHGUI* aSMESHGUI = SMESHGUI::GetSMESHGUI();
242   mySelection = theSelection;
243   aSMESHGUI->SetActiveDialogBox( ( QDialog* )this ) ;
244   myListBox->clear();
245   myIds.Clear();
246   myBusy = false;
247   myActor = 0;
248   emit ListContensChanged();
249
250   // main buttons
251   connect( myOkBtn,    SIGNAL( clicked() ), SLOT( onOk() ) );
252   connect( myCloseBtn, SIGNAL( clicked() ), SLOT( onClose() ) ) ;
253   connect( myApplyBtn, SIGNAL( clicked() ), SLOT( onApply() ) );
254
255   // selection and SMESHGUI
256   connect( mySelection, SIGNAL( currentSelectionChanged() ), SLOT( onSelectionDone() ) );
257   connect( aSMESHGUI, SIGNAL( SignalDeactivateActiveDialog() ), SLOT( onDeactivate() ) );
258   connect( aSMESHGUI, SIGNAL( SignalCloseAllDialogs() ), SLOT( onClose() ) );
259
260   // dialog controls
261   connect( myFilterBtn, SIGNAL( clicked() ), SLOT( onFilterBtn()   ) );
262   connect( myAddBtn   , SIGNAL( clicked() ), SLOT( onAddBtn()      ) );
263   connect( myRemoveBtn, SIGNAL( clicked() ), SLOT( onRemoveBtn()   ) );
264   connect( mySortBtn  , SIGNAL( clicked() ), SLOT( onSortListBtn() ) );
265   
266   connect( mySubmeshChk, SIGNAL( stateChanged( int ) ), SLOT( onSubmeshChk() ) );
267   connect( myGroupChk  , SIGNAL( stateChanged( int ) ), SLOT( onGroupChk()   ) );
268   connect( myToAllChk  , SIGNAL( stateChanged( int ) ), SLOT( onToAllChk()   ) );
269
270   if ( myEntityTypeGrp )
271     connect( myEntityTypeGrp, SIGNAL( clicked(int) ), SLOT( on3d2dChanged(int) ) );
272
273   connect( myListBox, SIGNAL( selectionChanged() ), SLOT( onListSelectionChanged() ) );
274
275   onSelectionDone();
276
277   // set selection mode
278   setSelectionMode();
279   updateButtons();
280 }
281
282 //=======================================================================
283 // name    : SMESHGUI_MultiEditDlg::onOk
284 // Purpose : SLOT called when "Ok" button pressed. 
285 //           Assign filters VTK viewer and close dialog
286 //=======================================================================
287 void SMESHGUI_MultiEditDlg::onOk()
288 {
289   if ( onApply() )
290     onClose();
291 }
292
293 //=======================================================================
294 // name    : SMESHGUI_MultiEditDlg::getIds
295 // Purpose : Retrive identifiers from list box
296 //=======================================================================
297 SMESH::long_array_var SMESHGUI_MultiEditDlg::getIds()
298 {
299   SMESH::long_array_var anIds = new SMESH::long_array;
300   
301   if ( myToAllChk->isChecked() )
302   {
303     myIds.Clear();
304     if ( myActor != 0 )
305     {
306       TVisualObjPtr aVisualObj = myActor->GetObject();
307       vtkUnstructuredGrid* aGrid = aVisualObj->GetUnstructuredGrid();
308       if ( aGrid != 0 )
309       {
310         for ( int i = 0, n = aGrid->GetNumberOfCells(); i < n; i++ )
311         {
312           vtkCell* aCell = aGrid->GetCell( i );
313           if ( aCell != 0 )
314           {
315             vtkTriangle* aTri = vtkTriangle::SafeDownCast(aCell);
316             vtkQuad*     aQua = vtkQuad::SafeDownCast(aCell);
317             vtkCell3D*   a3d  = vtkCell3D::SafeDownCast(aCell);
318
319             if ( aTri && myFilterType == SMESHGUI_TriaFilter || 
320                  aQua && myFilterType == SMESHGUI_QuadFilter ||
321                  ( aTri || aQua ) && myFilterType == SMESHGUI_FaceFilter ||
322                  a3d && myFilterType == SMESHGUI_VolumeFilter )
323             {
324               int anObjId = aVisualObj->GetElemObjId( i );
325               myIds.Add( anObjId );
326             }
327           }
328         }
329       }
330     }
331   }
332
333   anIds->length( myIds.Extent() );
334   TColStd_MapIteratorOfMapOfInteger anIter( myIds );
335   for ( int i = 0; anIter.More(); anIter.Next()  )
336   {
337     anIds[ i++ ] = anIter.Key();
338   }
339   return anIds._retn();
340 }
341
342 //=======================================================================
343 // name    : SMESHGUI_MultiEditDlg::onClose
344 // Purpose : SLOT called when "Close" button pressed. Close dialog
345 //=======================================================================
346 void SMESHGUI_MultiEditDlg::onClose()
347 {
348   QAD_Application::getDesktop()->SetSelectionMode( ActorSelection );
349   disconnect( mySelection, 0, this, 0 );
350   disconnect( SMESHGUI::GetSMESHGUI(), 0, this, 0 );
351   SMESHGUI::GetSMESHGUI()->ResetState();
352   
353   SMESH::RemoveFilter(SMESHGUI_EdgeFilter);
354   SMESH::RemoveFilter(SMESHGUI_FaceFilter);
355   SMESH::RemoveFilter(SMESHGUI_VolumeFilter);
356   SMESH::RemoveFilter(SMESHGUI_QuadFilter);
357   SMESH::RemoveFilter(SMESHGUI_TriaFilter);
358   SMESH::SetPickable();
359
360   mySelection->ClearIObjects();
361   mySelection->ClearFilters();
362   
363   reject();
364 }
365
366 //=======================================================================
367 // name    : SMESHGUI_MultiEditDlg::onSelectionDone
368 // Purpose : SLOT called when selection changed
369 //=======================================================================
370 void SMESHGUI_MultiEditDlg::onSelectionDone()
371 {
372   if ( myBusy || !isEnabled() ) return;
373   myBusy = true;
374
375   myMesh = SMESH::SMESH_Mesh::_nil();
376   myActor = 0;
377
378   int nbSel = mySelection->IObjectCount();
379   myListBox->clearSelection();
380
381   if ( mySubmeshChk->isChecked() || myGroupChk->isChecked() )
382   {
383     QLineEdit* aNameEdit = mySubmeshChk->isChecked() ? mySubmesh : myGroup;
384     int nbSel = mySelection->IObjectCount();
385     if ( nbSel == 1 )
386     {
387       Handle(SALOME_InteractiveObject) anIO = mySelection->firstIObject();
388       anIO.IsNull() ? aNameEdit->clear() : aNameEdit->setText( anIO->getName() );
389
390       if ( mySubmeshChk->isChecked() )
391       {
392         SMESH::SMESH_subMesh_var aSubMesh =
393           SMESH::IObjectToInterface<SMESH::SMESH_subMesh>( anIO );
394         if ( !aSubMesh->_is_nil() )
395           myMesh = aSubMesh->GetFather();
396       }
397       else
398       {
399         SMESH::SMESH_GroupBase_var aGroup =
400           SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>( anIO );
401         if ( !aGroup->_is_nil() )
402           myMesh = aGroup->GetMesh();
403       }
404     }
405     else if ( nbSel > 1 )
406     {
407       QString aStr = mySubmeshChk->isChecked() ? 
408         tr( "SMESH_SUBMESH_SELECTED" ) : tr( "SMESH_GROUP_SELECTED" );
409       aNameEdit->setText( aStr.arg( nbSel ) );
410     }
411     else
412       aNameEdit->clear();
413   }
414   else if ( nbSel == 1 )
415   {
416     QString aListStr = "";
417     int aNbItems = SMESH::GetNameOfSelectedElements(mySelection, aListStr);
418     if ( aNbItems > 0 )
419     {
420       QStringList anElements = QStringList::split(" ", aListStr);
421       QListBoxItem* anItem = 0;
422       for ( QStringList::iterator it = anElements.begin(); it != anElements.end(); ++it)
423       {
424         anItem = myListBox->findItem( *it, Qt::ExactMatch );
425         if (anItem) myListBox->setSelected( anItem, true );
426       }
427     }
428
429     myMesh = SMESH::GetMeshByIO( mySelection->firstIObject() );
430   }
431
432   if ( nbSel == 1 ) {
433     myActor = SMESH::FindActorByEntry(mySelection->firstIObject()->getEntry());
434     if ( !myActor && !myMesh->_is_nil() )
435       myActor = SMESH::FindActorByObject( myMesh );
436     VTKViewer_InteractorStyleSALOME* aStyle = SMESH::GetInteractorStyle();
437     Handle(VTKViewer_Filter) aFilter = aStyle->GetFilter( myFilterType );
438     if ( !aFilter.IsNull() && myActor ) {
439       aFilter->SetActor( myActor );
440       //SMESH::SetPickable( myActor );
441     }
442   }
443   myBusy = false;
444
445   updateButtons();
446 }
447
448 //=======================================================================
449 // name    : SMESHGUI_MultiEditDlg::onDeactivate
450 // Purpose : SLOT called when dialog must be deativated
451 //=======================================================================
452 void SMESHGUI_MultiEditDlg::onDeactivate()
453 {
454   setEnabled( false );
455 }
456
457 //=======================================================================
458 // name    : SMESHGUI_MultiEditDlg::enterEvent
459 // Purpose : Event filter
460 //=======================================================================
461 void SMESHGUI_MultiEditDlg::enterEvent( QEvent* )
462 {
463   if ( !isEnabled() ) {
464     SMESHGUI::GetSMESHGUI()->EmitSignalDeactivateDialog();
465     setEnabled( true );
466     setSelectionMode();
467   }
468 }
469
470
471 //=================================================================================
472 // function : closeEvent()
473 // purpose  :
474 //=================================================================================
475 void SMESHGUI_MultiEditDlg::closeEvent( QCloseEvent* e )
476 {
477   onClose() ;
478 }
479 //=======================================================================
480 //function : hideEvent
481 //purpose  : caused by ESC key
482 //=======================================================================
483
484 void SMESHGUI_MultiEditDlg::hideEvent ( QHideEvent * e )
485 {
486   if ( !isMinimized() )
487     onClose();
488 }
489
490 //=======================================================================
491 // name    : SMESHGUI_MultiEditDlg::onFilterBtn
492 // Purpose : SLOT. Called when "Filter" button pressed.
493 //           Start "Selection filters" dialog
494 //=======================================================================
495 void SMESHGUI_MultiEditDlg::onFilterBtn()
496 {
497   if ( myFilterDlg == 0 )
498   {
499     myFilterDlg = new SMESHGUI_FilterDlg( (QWidget*)parent(), entityType() ? SMESH::VOLUME : SMESH::FACE );
500     connect( myFilterDlg, SIGNAL( Accepted() ), SLOT( onFilterAccepted() ) );
501   }
502   else
503     myFilterDlg->Init( entityType() ? SMESH::VOLUME : SMESH::FACE );
504
505   myFilterDlg->SetSelection( mySelection );
506   myFilterDlg->SetMesh( myMesh );
507   myFilterDlg->SetSourceWg( myListBox );
508
509   myFilterDlg->show();
510 }
511
512 //=================================================================================
513 // function : onFilterAccepted()
514 // purpose  : SLOT. Called when Filter dlg closed with OK button.
515 //            Uncheck "Select submesh" and "Select group" checkboxes
516 //=================================================================================
517 void SMESHGUI_MultiEditDlg::onFilterAccepted()
518 {
519   myIds.Clear();
520   for ( int i = 0, n = myListBox->count(); i < n; i++ )
521     myIds.Add( myListBox->text( i ).toInt() );
522
523   emit ListContensChanged();
524
525   if ( mySubmeshChk->isChecked() || myGroupChk->isChecked() )
526   {
527     mySubmeshChk->blockSignals( true );
528     myGroupChk->blockSignals( true );
529     mySubmeshChk->setChecked( false );
530     myGroupChk->setChecked( false );
531     mySubmeshChk->blockSignals( false );
532     myGroupChk->blockSignals( false );
533   }
534   updateButtons();
535 }
536
537 //=======================================================================
538 // name    : SMESHGUI_MultiEditDlg::isIdValid
539 // Purpose : Verify whether Id of element satisfies to filters from viewer
540 //=======================================================================
541 bool SMESHGUI_MultiEditDlg::isIdValid( const int theId ) const
542 {
543   VTKViewer_InteractorStyleSALOME* aStyle = SMESH::GetInteractorStyle();
544   Handle(SMESHGUI_Filter) aFilter =
545     Handle(SMESHGUI_Filter)::DownCast( aStyle->GetFilter( myFilterType ) );
546   return ( !aFilter.IsNull() && aFilter->IsObjValid( theId ) );
547 }
548
549 //=======================================================================
550 // name    : SMESHGUI_MultiEditDlg::onAddBtn
551 // Purpose : SLOT. Called when "Add" button pressed.
552 //           Add selected in viewer entities in list box
553 //=======================================================================
554 void SMESHGUI_MultiEditDlg::onAddBtn()
555 {
556   int nbSelected = mySelection->IObjectCount();
557   if ( nbSelected == 0 ) 
558     return;
559
560   TColStd_IndexedMapOfInteger toBeAdded;
561   
562   if ( !mySubmeshChk->isChecked() && !myGroupChk->isChecked() ) 
563   {
564     if ( nbSelected == 1 ) 
565       SMESH::GetSelected( mySelection, toBeAdded );
566   }
567   else if ( mySubmeshChk->isChecked() ) 
568   {
569     SALOME_ListIteratorOfListIO anIter( mySelection->StoredIObjects() );
570     for ( ; anIter.More(); anIter.Next() )
571     {
572       SMESH::SMESH_subMesh_var aSubMesh = SMESH::IObjectToInterface<SMESH::SMESH_subMesh>( anIter.Value() );
573       if ( !aSubMesh->_is_nil() )
574       {
575         if ( !myMesh->_is_nil() && aSubMesh->GetFather()->GetId() == myMesh->GetId() )
576         {
577           SMESH::long_array_var anIds = aSubMesh->GetElementsId();
578           for ( int i = 0, n = anIds->length(); i < n; i++ )
579           {
580             if ( isIdValid( anIds[ i ] ) )
581               toBeAdded.Add( anIds[ i ] );
582           }
583         }
584       }
585     }
586   }
587   else if ( myGroupChk->isChecked() ) 
588   {
589     SALOME_ListIteratorOfListIO anIter( mySelection->StoredIObjects() );
590     for ( ; anIter.More(); anIter.Next() )
591     {
592       SMESH::SMESH_GroupBase_var aGroup =
593         SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>( anIter.Value() );
594       if ( !aGroup->_is_nil() && ( aGroup->GetType() == SMESH::FACE || aGroup->GetType() == SMESH::VOLUME ) )
595       {
596         if ( !myMesh->_is_nil() && aGroup->GetMesh()->GetId() == myMesh->GetId() )
597         {
598           SMESH::long_array_var anIds = aGroup->GetListOfID();
599           for ( int i = 0, n = anIds->length(); i < n; i++ )
600           {
601             if ( isIdValid( anIds[ i ] ) )
602               toBeAdded.Add( anIds[ i ] );
603           }
604         }
605       }
606     }
607   }
608
609   myBusy = true;
610   bool isGroupOrSubmesh = ( mySubmeshChk->isChecked() || myGroupChk->isChecked() );
611   mySubmeshChk->setChecked( false );
612   myGroupChk->setChecked( false );
613   for( int i = 1; i <= toBeAdded.Extent(); i++ )
614     if ( myIds.Add( toBeAdded(i) ) ) {
615       QListBoxItem * item = new QListBoxText( QString( "%1" ).arg( toBeAdded(i) ));
616       myListBox->insertItem( item );
617       myListBox->setSelected( item, true );
618     }
619   myBusy = false;
620
621   emit ListContensChanged(); 
622
623   if ( isGroupOrSubmesh )
624     onListSelectionChanged();
625
626   updateButtons();
627 }
628
629 //=======================================================================
630 // name    : SMESHGUI_MultiEditDlg::updateButtons
631 // Purpose : Enable/disable buttons of dialog in accordance with current state
632 //=======================================================================
633 void SMESHGUI_MultiEditDlg::updateButtons()
634 {
635   bool isOk = isValid(false);
636   myOkBtn->setEnabled( isOk );
637   myApplyBtn->setEnabled( isOk );
638
639   bool isListBoxNonEmpty = myListBox->count() > 0;
640   bool isToAll = myToAllChk->isChecked();
641   myFilterBtn->setEnabled( !isToAll );
642   myRemoveBtn->setEnabled( isListBoxNonEmpty && !isToAll );
643   mySortBtn->setEnabled( isListBoxNonEmpty &&!isToAll );
644   
645   if ( isToAll ||
646        myMesh->_is_nil() ||
647        mySelection->IObjectCount() != 1 ||
648        (SMESH::IObjectToInterface<SMESH::SMESH_subMesh>( mySelection->firstIObject() )->_is_nil() &&
649         SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>( mySelection->firstIObject() )->_is_nil() &&
650         SMESH::IObjectToInterface<SMESH::SMESH_Mesh>( mySelection->firstIObject() )->_is_nil()) )
651     myAddBtn->setEnabled( false );
652   else
653     myAddBtn->setEnabled( true );
654   
655   mySubmeshChk->setEnabled( !isToAll );
656   mySubmeshBtn->setEnabled( mySubmeshChk->isChecked() );
657   mySubmesh->setEnabled( mySubmeshChk->isChecked() );
658   
659   myGroupChk->setEnabled( !isToAll );
660   myGroupBtn->setEnabled( myGroupChk->isChecked() );
661   myGroup->setEnabled( myGroupChk->isChecked() );
662   
663   if ( !mySubmeshChk->isChecked() )
664     mySubmesh->clear();
665   if ( !myGroupChk->isChecked() )
666     myGroup->clear();
667     
668 }
669
670 //=======================================================================
671 // name    : SMESHGUI_MultiEditDlg::onRemoveBtn
672 // Purpose : SLOT. Called when "Remove" button pressed.
673 //           Remove selected in list box entities
674 //=======================================================================
675 void SMESHGUI_MultiEditDlg::onRemoveBtn()
676 {
677   myBusy = true;
678   
679   for ( int i = 0, n = myListBox->count(); i < n; i++ )
680   {
681     for ( int i = myListBox->count(); i > 0; i--) {
682       if ( myListBox->isSelected( i - 1 ) ) 
683       {
684         int anId = myListBox->text( i - 1 ).toInt();
685         myIds.Remove( anId );
686         myIds.Remove( anId );
687               myListBox->removeItem( i-1 );
688       }
689     }        
690   }
691   myBusy = false;
692
693   emit ListContensChanged();  
694   updateButtons();
695 }
696
697 //=======================================================================
698 // name    : SMESHGUI_MultiEditDlg::onSortListBtn
699 // Purpose : SLOT. Called when "Sort list" button pressed.
700 //           Sort entities of list box
701 //=======================================================================
702 void SMESHGUI_MultiEditDlg::onSortListBtn()
703 {
704   myBusy = true;
705
706   int i, k = myListBox->count();
707   if ( k > 0 ) 
708   {
709     QStringList aSelected;
710     std::vector<int> anArray( k );
711     QListBoxItem* anItem;
712     for ( anItem = myListBox->firstItem(), i = 0; anItem != 0; anItem = anItem->next(), i++) 
713     {
714       anArray[ i ] = anItem->text().toInt();
715       if ( anItem->isSelected() ) 
716         aSelected.append( anItem->text() );
717     }
718     
719     std::sort( anArray.begin(), anArray.end() );
720     myListBox->clear();
721     for ( i = 0; i < k; i++ ) 
722       myListBox->insertItem( QString::number( anArray[ i ] ) );
723
724     for ( QStringList::iterator it = aSelected.begin(); it != aSelected.end(); ++it ) 
725     {
726       anItem = myListBox->findItem( *it, Qt::ExactMatch );
727       if ( anItem ) 
728         myListBox->setSelected( anItem, true );
729     }
730   }
731   myBusy = false;
732 }
733
734 //=======================================================================
735 // name    : SMESHGUI_MultiEditDlg::onListSelectionChanged
736 // Purpose : SLOT. Called when selection in list box changed.
737 //           Highlight in selected entities
738 //=======================================================================
739 void SMESHGUI_MultiEditDlg::onListSelectionChanged()
740 {
741   if ( myActor == 0 || myBusy )
742     return;
743   
744   if ( mySubmeshChk->isChecked() || myGroupChk->isChecked() ) 
745     return;
746
747   SMESH_Actor * anActor = SMESH::FindActorByObject( myMesh );
748   if ( !anActor )
749     anActor = myActor;
750   TVisualObjPtr anObj = anActor->GetObject();
751
752   TColStd_MapOfInteger anIndexes;
753   for ( QListBoxItem* anItem = myListBox->firstItem(); anItem != 0; anItem = anItem->next() ) 
754   {
755     if ( anItem->isSelected() ) 
756     {
757       int anId = anItem->text().toInt();
758       if ( anObj->GetElemVTKId( anId ) >= 0 ) // avoid exception in hilight
759         anIndexes.Add(anId);
760     }
761   }
762   
763   mySelection->ClearIObjects();
764   mySelection->AddOrRemoveIndex( anActor->getIO(), anIndexes, false, false );
765   mySelection->AddIObject( anActor->getIO() );
766 }
767
768 //=======================================================================
769 // name    : SMESHGUI_MultiEditDlg::onSubmeshChk
770 // Purpose : SLOT. Called when state of "SubMesh" check box changed.
771 //           Activate/deactivate selection of submeshes
772 //=======================================================================
773 void SMESHGUI_MultiEditDlg::onSubmeshChk()
774 {
775   bool isChecked = mySubmeshChk->isChecked();
776   mySubmeshBtn->setEnabled( isChecked );
777   mySubmesh->setEnabled( isChecked );
778   if ( !isChecked )
779     mySubmesh->clear();
780   if ( isChecked && myGroupChk->isChecked() )
781       myGroupChk->setChecked( false );
782       
783   setSelectionMode();      
784 }
785
786 //=======================================================================
787 // name    : SMESHGUI_MultiEditDlg::onGroupChk
788 // Purpose : SLOT. Called when state of "Group" check box changed.
789 //           Activate/deactivate selection of groupes
790 //=======================================================================
791 void SMESHGUI_MultiEditDlg::onGroupChk()
792 {
793   bool isChecked = myGroupChk->isChecked();
794   myGroupBtn->setEnabled( isChecked );
795   myGroup->setEnabled( isChecked );
796   if ( !isChecked )
797     myGroup->clear();
798   if ( isChecked && mySubmeshChk->isChecked() )
799       mySubmeshChk->setChecked( false );
800
801   setSelectionMode();
802 }
803
804 //=======================================================================
805 // name    : SMESHGUI_MultiEditDlg::onToAllChk
806 // Purpose : SLOT. Called when state of "Apply to all" check box changed.
807 //           Activate/deactivate selection 
808 //=======================================================================
809 void SMESHGUI_MultiEditDlg::onToAllChk()
810 {
811   bool isChecked = myToAllChk->isChecked();
812
813   if ( isChecked )
814     myListBox->clear();
815
816   myIds.Clear();
817
818   emit ListContensChanged();
819     
820   updateButtons();
821   setSelectionMode();
822
823   if ( myActor )
824     mySelection->AddIObject( myActor->getIO(), true );
825 }
826
827
828 //=======================================================================
829 // name    : SMESHGUI_MultiEditDlg::setSelectionMode
830 // Purpose : Set selection mode
831 //=======================================================================
832 void SMESHGUI_MultiEditDlg::setSelectionMode()
833 {
834   SMESH::RemoveFilter(SMESHGUI_EdgeFilter);
835   SMESH::RemoveFilter(SMESHGUI_FaceFilter);
836   SMESH::RemoveFilter(SMESHGUI_VolumeFilter);
837   SMESH::RemoveFilter(SMESHGUI_QuadFilter);
838   SMESH::RemoveFilter(SMESHGUI_TriaFilter);
839   SMESH::SetPickable();
840
841   mySelection->ClearIObjects();
842   mySelection->ClearFilters();
843   
844   if ( mySubmeshChk->isChecked() )
845   {
846     QAD_Application::getDesktop()->SetSelectionMode( ActorSelection, true );
847     mySelection->AddFilter( mySubmeshFilter );
848   }
849   else if ( myGroupChk->isChecked() )
850   {
851     QAD_Application::getDesktop()->SetSelectionMode( ActorSelection, true );
852     mySelection->AddFilter( myGroupFilter );
853   }
854   if ( myFilterType == SMESHGUI_VolumeFilter ) {
855     QAD_Application::getDesktop()->SetSelectionMode( VolumeSelection, true );
856     SMESH::SetFilter( new SMESHGUI_VolumesFilter() );
857   }
858   else {
859     QAD_Application::getDesktop()->SetSelectionMode( FaceSelection, true );
860     if ( myFilterType == SMESHGUI_TriaFilter )
861       SMESH::SetFilter( new SMESHGUI_TriangleFilter() );
862     else if ( myFilterType == SMESHGUI_QuadFilter )
863       SMESH::SetFilter( new SMESHGUI_QuadrangleFilter() );
864     else
865       SMESH::SetFilter( new SMESHGUI_FacesFilter() );
866   }
867 }
868
869 //=======================================================================
870 // name    : SMESHGUI_MultiEditDlg::onApply
871 // Purpose : SLOT. Called when "Apply" button clicked. 
872 //=======================================================================
873 bool SMESHGUI_MultiEditDlg::onApply()
874 {
875   if ( SMESHGUI::GetSMESHGUI()->ActiveStudyLocked() )
876     return false;
877   if ( !isValid( true ) )
878     return false;
879
880   SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
881   if ( aMeshEditor->_is_nil()  )
882     return false;
883
884   myBusy = true;
885
886   SMESH::long_array_var anIds = getIds();
887
888   bool aResult = process( aMeshEditor, anIds.inout() );
889   if ( aResult )
890   {
891     if ( myActor )
892     {
893       mySelection->ClearIObjects();
894       SMESH::UpdateView();
895       mySelection->AddIObject( myActor->getIO(), false );
896     }
897
898     myListBox->clear();
899     myIds.Clear();
900     emit ListContensChanged();
901
902     updateButtons();
903   }
904
905   myBusy = false;
906   return aResult;
907 }
908
909 //=======================================================================
910 // name    : SMESHGUI_MultiEditDlg::on3d2dChanged
911 // Purpose : 
912 //=======================================================================
913 void SMESHGUI_MultiEditDlg::on3d2dChanged(int type)
914 {
915   if ( myEntityType != type ) {
916     myEntityType = type;
917     
918     myListBox->clear();
919     myIds.Clear();
920
921     emit ListContensChanged();
922     
923     updateButtons();
924
925     if ( type )
926       myFilterType = SMESHGUI_VolumeFilter;
927     else 
928       myFilterType = SMESHGUI_FaceFilter;
929     setSelectionMode();
930
931     myActor = 0;
932   }
933 }
934
935 //=======================================================================
936 // name    : SMESHGUI_MultiEditDlg::entityType
937 // Purpose : 
938 //=======================================================================
939
940 int SMESHGUI_MultiEditDlg::entityType() 
941 {
942   return myEntityType;
943 }
944
945 /*
946   Class       : SMESHGUI_ChangeOrientationDlg
947   Description : Modification of orientation of faces
948 */
949
950 SMESHGUI_ChangeOrientationDlg::SMESHGUI_ChangeOrientationDlg( QWidget*          theParent, 
951                                                               SALOME_Selection* theSelection,
952                                                               const char*       theName )
953 : SMESHGUI_MultiEditDlg( theParent, theSelection, SMESHGUI_FaceFilter, true, theName )
954 {
955   setCaption( tr( "CAPTION" ) );
956 }
957
958 SMESHGUI_ChangeOrientationDlg::~SMESHGUI_ChangeOrientationDlg()
959 {
960 }
961
962 bool SMESHGUI_ChangeOrientationDlg::process( SMESH::SMESH_MeshEditor_ptr theEditor,
963                                              const SMESH::long_array&    theIds )
964 {
965   return theEditor->Reorient( theIds );
966 }
967
968 /*
969   Class       : SMESHGUI_UnionOfTrianglesDlg
970   Description : Construction of quadrangles by automatic association of triangles
971 */
972
973 SMESHGUI_UnionOfTrianglesDlg::SMESHGUI_UnionOfTrianglesDlg( QWidget*          theParent,
974                                                             SALOME_Selection* theSelection,
975                                                             const char*       theName )
976 : SMESHGUI_MultiEditDlg( theParent, theSelection, SMESHGUI_TriaFilter, false, theName )
977 {
978   setCaption( tr( "CAPTION" ) );
979 }
980
981 SMESHGUI_UnionOfTrianglesDlg::~SMESHGUI_UnionOfTrianglesDlg()
982 {
983 }
984
985 bool SMESHGUI_UnionOfTrianglesDlg::process( SMESH::SMESH_MeshEditor_ptr theEditor,
986                                             const SMESH::long_array&    theIds )
987 {
988   return theEditor->TriToQuad(theIds, SMESH::NumericalFunctor::_nil(), 1. );
989 }
990
991 /*
992   Class       : SMESHGUI_CuttingOfQuadsDlg
993   Description : Construction of quadrangles by automatic association of triangles
994 */
995
996 SMESHGUI_CuttingOfQuadsDlg::SMESHGUI_CuttingOfQuadsDlg( QWidget*          theParent,
997                                                         SALOME_Selection* theSelection,
998                                                         const char*       theName )
999 : SMESHGUI_MultiEditDlg( theParent, theSelection, SMESHGUI_QuadFilter, false, theName )
1000 {
1001
1002   setCaption( tr( "CAPTION" ) );
1003   myPreviewActor = 0;
1004
1005   myUseDiagChk = new QCheckBox( tr( "USE_DIAGONAL_2_4" ), mySelGrp );
1006   myPreviewChk = new QCheckBox( tr( "PREVIEW" ), mySelGrp );
1007
1008   connect( myPreviewChk, SIGNAL( stateChanged( int ) ), this, SLOT( onPreviewChk() ) );
1009   connect( myUseDiagChk, SIGNAL( stateChanged( int ) ), this, SLOT( onPreviewChk() ) );
1010   connect( this, SIGNAL( ListContensChanged() ), this, SLOT( onPreviewChk() ) );
1011 }
1012
1013 SMESHGUI_CuttingOfQuadsDlg::~SMESHGUI_CuttingOfQuadsDlg()
1014 {
1015 }
1016
1017 void SMESHGUI_CuttingOfQuadsDlg::onClose()
1018 {
1019   erasePreview();
1020   SMESHGUI_MultiEditDlg::onClose();
1021 }
1022
1023 bool SMESHGUI_CuttingOfQuadsDlg::process( SMESH::SMESH_MeshEditor_ptr theEditor,
1024                                           const SMESH::long_array&    theIds )
1025 {
1026   return theEditor->SplitQuad( theIds, !myUseDiagChk->isChecked() );
1027 }
1028
1029 void SMESHGUI_CuttingOfQuadsDlg::onPreviewChk()
1030 {
1031   myPreviewChk->isChecked() ? displayPreview() : erasePreview();
1032 }
1033
1034 void SMESHGUI_CuttingOfQuadsDlg::erasePreview()
1035 {
1036   if ( myPreviewActor == 0 )
1037     return;
1038     
1039   if ( VTKViewer_ViewFrame* vf = SMESH::GetCurrentVtkView() )
1040   {
1041     vf->RemoveActor(myPreviewActor);
1042     vf->Repaint();
1043   }
1044   myPreviewActor->Delete();
1045   myPreviewActor = 0;
1046 }
1047
1048 void SMESHGUI_CuttingOfQuadsDlg::displayPreview()
1049 {
1050   if ( myActor == 0 )
1051     return;
1052
1053   if ( myPreviewActor != 0 )
1054     erasePreview();
1055
1056   // get Ids of elements
1057   SMESH::long_array_var anElemIds = getIds();
1058   if ( getIds()->length() == 0 )
1059     return;
1060
1061   SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh();
1062   if ( aMesh == 0 )
1063     return;
1064
1065   bool isDiag24 = myUseDiagChk->isChecked();
1066
1067   //Create grid
1068   vtkUnstructuredGrid* aGrid = vtkUnstructuredGrid::New();
1069     
1070   vtkIdType aNbCells = anElemIds->length() * 2;
1071   vtkIdType aCellsSize = 4 * aNbCells;
1072   vtkCellArray* aConnectivity = vtkCellArray::New();
1073   aConnectivity->Allocate( aCellsSize, 0 );
1074
1075   vtkPoints* aPoints = vtkPoints::New();
1076   aPoints->SetNumberOfPoints( anElemIds->length() * 4 );
1077   
1078   vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
1079   aCellTypesArray->SetNumberOfComponents( 1 );
1080   aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
1081
1082   vtkIdList *anIdList = vtkIdList::New();
1083   anIdList->SetNumberOfIds( 3 );
1084
1085   TColStd_DataMapOfIntegerInteger anIdToVtk;
1086
1087   int aNodes[ 4 ];
1088   int nbPoints = -1;
1089   for ( int i = 0, n = anElemIds->length(); i < n; i++ )
1090   {
1091     const SMDS_MeshElement* anElem = aMesh->FindElement( anElemIds[ i ] );
1092     if ( anElem == 0 || anElem->NbNodes() != 4 )
1093       continue;
1094       
1095     SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
1096     int k = 0;
1097     while( anIter->more() )
1098       if ( const SMDS_MeshNode* aNode = (SMDS_MeshNode*)anIter->next() )
1099       {
1100         if ( !anIdToVtk.IsBound( aNode->GetID() ) )
1101         {
1102           aPoints->SetPoint( ++nbPoints, aNode->X(), aNode->Y(), aNode->Z() );
1103           anIdToVtk.Bind( aNode->GetID(), nbPoints );
1104         }
1105         
1106         aNodes[ k++ ] = aNode->GetID();
1107       }
1108
1109     if ( k != 4 )
1110       continue;
1111
1112     if ( !isDiag24 )
1113     {
1114       anIdList->SetId( 0, anIdToVtk( aNodes[ 0 ] ) );
1115       anIdList->SetId( 1, anIdToVtk( aNodes[ 1 ] ) );
1116       anIdList->SetId( 2, anIdToVtk( aNodes[ 2 ] ) );
1117       aConnectivity->InsertNextCell( anIdList );
1118       aCellTypesArray->InsertNextValue( VTK_TRIANGLE );
1119
1120       anIdList->SetId( 0, anIdToVtk( aNodes[ 2 ] ) );
1121       anIdList->SetId( 1, anIdToVtk( aNodes[ 3 ] ) );
1122       anIdList->SetId( 2, anIdToVtk( aNodes[ 0 ] ) );
1123       aConnectivity->InsertNextCell( anIdList );
1124       aCellTypesArray->InsertNextValue( VTK_TRIANGLE );
1125     }
1126     else
1127     {
1128       anIdList->SetId( 0, anIdToVtk( aNodes[ 1 ] ) );
1129       anIdList->SetId( 1, anIdToVtk( aNodes[ 2 ] ) );
1130       anIdList->SetId( 2, anIdToVtk( aNodes[ 3 ] ) );
1131       aConnectivity->InsertNextCell( anIdList );
1132       aCellTypesArray->InsertNextValue( VTK_TRIANGLE );
1133
1134       anIdList->SetId( 0, anIdToVtk( aNodes[ 3 ] ) );
1135       anIdList->SetId( 1, anIdToVtk( aNodes[ 0 ] ) );
1136       anIdList->SetId( 2, anIdToVtk( aNodes[ 1 ] ) );
1137       aConnectivity->InsertNextCell( anIdList );
1138       aCellTypesArray->InsertNextValue( VTK_TRIANGLE );
1139     }
1140   }
1141
1142   vtkIntArray* aCellLocationsArray = vtkIntArray::New();
1143   aCellLocationsArray->SetNumberOfComponents( 1 );
1144   aCellLocationsArray->SetNumberOfTuples( aNbCells );
1145
1146   aConnectivity->InitTraversal();
1147   for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
1148     aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
1149
1150   aGrid->SetPoints( aPoints );
1151   aGrid->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
1152
1153   // Create and display actor
1154   vtkDataSetMapper* aMapper = vtkDataSetMapper::New();
1155   aMapper->SetInput( aGrid );
1156   
1157   myPreviewActor = SALOME_Actor::New();
1158   myPreviewActor->PickableOff();
1159   myPreviewActor->SetMapper( aMapper );
1160
1161   vtkProperty* aProp = vtkProperty::New();
1162   aProp->SetRepresentationToWireframe();
1163   aProp->SetColor( 250, 0, 250 );
1164   aProp->SetLineWidth( myActor->GetLineWidth() + 1 );
1165   myPreviewActor->SetProperty( aProp );
1166
1167   SMESH::GetCurrentVtkView()->AddActor( myPreviewActor );
1168   SMESH::GetCurrentVtkView()->Repaint();
1169
1170   aProp->Delete();
1171   aPoints->Delete();
1172   aConnectivity->Delete();
1173   aGrid->Delete();
1174   aMapper->Delete();
1175   anIdList->Delete();
1176   aCellTypesArray->Delete();
1177   aCellLocationsArray->Delete();
1178 }
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201