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