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