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