1 // SMESH SMESHGUI : GUI for SMESH component
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : SMESHGUI_SingleEditDlg.cxx
25 // Author : Sergey LITONIN
28 #include "SMESHGUI_SingleEditDlg.h"
30 #include "QAD_Desktop.h"
33 #include "SMESHGUI_Utils.h"
34 #include "SMESHGUI_VTKUtils.h"
35 #include "SMESHGUI_MeshUtils.h"
37 #include "SMESHGUI_SpinBox.h"
39 #include "utilities.h"
40 #include "SALOME_Selection.h"
41 #include "SMESH_Actor.h"
42 #include "SMDS_Mesh.hxx"
46 #include <qlineedit.h>
47 #include <qpushbutton.h>
48 #include <qgroupbox.h>
50 #include <qmessagebox.h>
51 #include <qvalidator.h>
59 Class : SMESHGUI_DiagValidator
60 Description : validate munual input of edge like "id1-id2"
62 class SMESHGUI_DiagValidator: public QValidator
66 SMESHGUI_DiagValidator(QWidget * parent, const char * name = 0):
67 QValidator(parent,name) {}
69 State validate ( QString & text, int & pos) const
71 text.stripWhiteSpace();
72 text.replace( QRegExp("[^0-9]+"), "-" );
75 int ind = text.find( QRegExp("-[0-9]+-"));
76 if ( ind > 0 ) { // leave only two ids
77 ind = text.find( '-', ind + 1 );
81 if ( pos > text.length() )
88 Class : SMESHGUI_SingleEditDlg
89 Description : Inversion of the diagonal of a pseudo-quadrangle formed by
90 2 neighboring triangles with 1 common edge
93 //=======================================================================
94 // name : SMESHGUI_SingleEditDlg::SMESHGUI_SingleEditDlg
95 // Purpose : Constructor
96 //=======================================================================
97 SMESHGUI_SingleEditDlg::SMESHGUI_SingleEditDlg( QWidget* theParent,
98 SALOME_Selection* theSelection,
100 : QDialog( theParent, theName, false,
101 WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu )
103 //setCaption( tr( "CAPTION" ) );
105 QVBoxLayout* aDlgLay = new QVBoxLayout( this, MARGIN, SPACING );
107 QFrame* aMainFrame = createMainFrame ( this );
108 QFrame* aBtnFrame = createButtonFrame( this );
110 aDlgLay->addWidget( aMainFrame );
111 aDlgLay->addWidget( aBtnFrame );
113 aDlgLay->setStretchFactor( aMainFrame, 1 );
115 Init( theSelection ) ;
118 //=======================================================================
119 // name : SMESHGUI_SingleEditDlg::createMainFrame
120 // Purpose : Create frame containing dialog's input fields
121 //=======================================================================
122 QFrame* SMESHGUI_SingleEditDlg::createMainFrame( QWidget* theParent )
124 QGroupBox* aMainGrp = new QGroupBox( 1, Qt::Vertical, tr( "EDGE_BETWEEN" ), theParent );
126 QPixmap aPix( QAD_Desktop::getResourceManager()->loadPixmap( "SMESH",tr( "ICON_SELECT" ) ) );
128 new QLabel( tr( "SMESH_EDGE" ), aMainGrp );
129 ( new QPushButton( aMainGrp ) )->setPixmap( aPix );
130 myEdge = new QLineEdit( aMainGrp );
131 myEdge->setValidator( new SMESHGUI_DiagValidator( this, "validator" ));
136 //=======================================================================
137 // name : SMESHGUI_SingleEditDlg::createButtonFrame
138 // Purpose : Create frame containing buttons
139 //=======================================================================
140 QFrame* SMESHGUI_SingleEditDlg::createButtonFrame( QWidget* theParent )
142 QFrame* aFrame = new QFrame( theParent );
143 aFrame->setFrameStyle( QFrame::Box | QFrame::Sunken );
145 myOkBtn = new QPushButton( tr( "SMESH_BUT_OK" ), aFrame );
146 myApplyBtn = new QPushButton( tr( "SMESH_BUT_APPLY" ), aFrame );
147 myCloseBtn = new QPushButton( tr( "SMESH_BUT_CLOSE" ), aFrame );
149 QSpacerItem* aSpacer = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
151 QHBoxLayout* aLay = new QHBoxLayout( aFrame, MARGIN, SPACING );
153 aLay->addWidget( myOkBtn );
154 aLay->addWidget( myApplyBtn );
155 aLay->addItem( aSpacer);
156 aLay->addWidget( myCloseBtn );
161 //=======================================================================
162 // name : SMESHGUI_SingleEditDlg::isValid
163 // Purpose : Verify validity of input data
164 //=======================================================================
165 bool SMESHGUI_SingleEditDlg::isValid( const bool theMess ) const
168 return getNodeIds( myEdge->text(), id1, id2 );
171 //=======================================================================
172 // name : SMESHGUI_SingleEditDlg::getNodeIds
173 // Purpose : Retrieve node ids from string
174 //=======================================================================
175 bool SMESHGUI_SingleEditDlg::getNodeIds( const QString& theStr, int& theId1, int& theId2 ) const
177 if ( !theStr.contains( '-' ) )
181 QString str1 = theStr.section( '-', 0, 0, QString::SectionSkipEmpty );
182 QString str2 = theStr.section( '-', 1, 1, QString::SectionSkipEmpty );
183 theId1 = str1.toInt( &ok1 );
184 theId2 = str2.toInt( &ok2 );
189 //=======================================================================
190 // name : SMESHGUI_SingleEditDlg::~SMESHGUI_SingleEditDlg
191 // Purpose : Destructor
192 //=======================================================================
193 SMESHGUI_SingleEditDlg::~SMESHGUI_SingleEditDlg()
197 //=======================================================================
198 // name : SMESHGUI_SingleEditDlg::Init
199 // Purpose : Init dialog fields, connect signals and slots, show dialog
200 //=======================================================================
201 void SMESHGUI_SingleEditDlg::Init( SALOME_Selection* theSelection )
203 mySelection = theSelection;
204 SMESHGUI* aSMESHGUI = SMESHGUI::GetSMESHGUI();
205 aSMESHGUI->SetActiveDialogBox( ( QDialog* )this ) ;
210 connect( myOkBtn, SIGNAL( clicked() ), SLOT( onOk() ) );
211 connect( myCloseBtn, SIGNAL( clicked() ), SLOT( onClose() ) ) ;
212 connect( myApplyBtn, SIGNAL( clicked() ), SLOT( onApply() ) );
214 // selection and SMESHGUI
215 connect( mySelection, SIGNAL( currentSelectionChanged() ), SLOT( onSelectionDone() ) );
216 connect( aSMESHGUI, SIGNAL( SignalDeactivateActiveDialog() ), SLOT( onDeactivate() ) );
217 connect( aSMESHGUI, SIGNAL( SignalCloseAllDialogs() ), SLOT( onClose() ) );
218 connect( myEdge, SIGNAL( textChanged(const QString&)), SLOT( onTextChange(const QString&)));
220 myOkBtn->setEnabled( false );
221 myApplyBtn->setEnabled( false );
225 aSMESHGUI->DefineDlgPosition( this, x, y );
229 // set selection mode
230 QAD_Application::getDesktop()->SetSelectionMode( EdgeOfCellSelection, true );
237 //=======================================================================
238 // name : SMESHGUI_SingleEditDlg::onOk
239 // Purpose : SLOT called when "Ok" button pressed.
240 // Assign filters VTK viewer and close dialog
241 //=======================================================================
242 void SMESHGUI_SingleEditDlg::onOk()
248 //=======================================================================
249 // name : SMESHGUI_SingleEditDlg::onClose
250 // Purpose : SLOT called when "Close" button pressed. Close dialog
251 //=======================================================================
252 void SMESHGUI_SingleEditDlg::onClose()
254 QAD_Application::getDesktop()->SetSelectionMode( ActorSelection );
255 mySelection->ClearIObjects();
256 disconnect( mySelection, 0, this, 0 );
257 disconnect( SMESHGUI::GetSMESHGUI(), 0, this, 0 );
258 SMESHGUI::GetSMESHGUI()->ResetState() ;
262 //=======================================================================
263 //function : findTriangles
264 //purpose : find triangles sharing theNode1-theNode2 link
265 // THIS IS A PIECE OF SMESH_MeshEditor.cxx
266 // TO DO: make it available in SMDS for ex.
267 //=======================================================================
269 static bool findTriangles(const SMDS_MeshNode * theNode1,
270 const SMDS_MeshNode * theNode2,
271 const SMDS_MeshElement*& theTria1,
272 const SMDS_MeshElement*& theTria2)
274 if ( !theNode1 || !theNode2 ) return false;
276 theTria1 = theTria2 = 0;
278 set< const SMDS_MeshElement* > emap;
279 SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator();
281 const SMDS_MeshElement* elem = it->next();
282 if ( elem->GetType() == SMDSAbs_Face && elem->NbNodes() == 3 )
285 it = theNode2->GetInverseElementIterator();
287 const SMDS_MeshElement* elem = it->next();
288 if ( elem->GetType() == SMDSAbs_Face &&
289 emap.find( elem ) != emap.end() )
297 return ( theTria1 && theTria2 );
300 //=======================================================================
301 //function : onTextChange
303 //=======================================================================
305 void SMESHGUI_SingleEditDlg::onTextChange( const QString& theNewText )
307 if ( myBusy ) return;
309 myOkBtn->setEnabled( false );
310 myApplyBtn->setEnabled( false );
312 // hilight entered edge
313 SMDS_Mesh* aMesh = 0;
315 aMesh = myActor->GetObject()->GetMesh();
318 myBusy = true; // block onSelectionDone()
319 mySelection->ClearIObjects();
320 mySelection->AddIObject( myActor->getIO() );
323 QStringList aListId = QStringList::split( "-", theNewText, false);
324 if ( aListId.count() != 2 )
326 const SMDS_MeshNode* a2Nodes[2];
329 for ( i = 0; i < aListId.count(); i++ ) {
330 const SMDS_MeshNode * n = aMesh->FindNode( aListId[ i ].toInt() );
337 // find a triangle and an edge nb
338 const SMDS_MeshElement* tria[2];
340 a2Nodes[0] != a2Nodes[1] &&
341 findTriangles( a2Nodes[0],
345 myBusy = true; // block onSelectionDone()
346 mySelection->AddOrRemoveIndex (myActor->getIO(), tria[0]->GetID(), true, false);
348 const SMDS_MeshNode* a3Nodes [3];
349 SMDS_ElemIteratorPtr it;
351 for (i = 0, it = tria[0]->nodesIterator(); it->more(); i++ ) {
352 a3Nodes[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
354 if (( a3Nodes[ i ] == a2Nodes[ 0 ] && a3Nodes[ i - 1] == a2Nodes[ 1 ] ) ||
355 ( a3Nodes[ i ] == a2Nodes[ 1 ] && a3Nodes[ i - 1] == a2Nodes[ 0 ] ) ) {
361 mySelection->AddOrRemoveIndex( myActor->getIO(), -edgeInd-1, true, true );
364 myOkBtn->setEnabled( true );
365 myApplyBtn->setEnabled( true );
369 //=======================================================================
370 // name : SMESHGUI_SingleEditDlg::onSelectionDone
371 // Purpose : SLOT called when selection changed
372 //=======================================================================
373 void SMESHGUI_SingleEditDlg::onSelectionDone()
375 if ( myBusy ) return;
377 int anId1 = 0, anId2 = 0;
379 myOkBtn->setEnabled( false );
380 myApplyBtn->setEnabled( false );
382 if ( mySelection->IObjectCount() != 1 )
388 myActor = SMESH::FindActorByEntry( mySelection->firstIObject()->getEntry() );
389 SMDS_Mesh* aMesh = 0;
391 aMesh = myActor->GetObject()->GetMesh();
395 if (SMESH::GetEdgeNodes( mySelection, anId1, anId2 ) >= 1 ) {
396 QString aText = QString( "%1-%2" ).arg( anId1 ).arg( anId2 );
398 myEdge->setText( aText );
401 const SMDS_MeshElement* tria[2];
402 if ( findTriangles( aMesh->FindNode( anId1 ), aMesh->FindNode( anId2 ), tria[0],tria[1]))
404 myOkBtn->setEnabled( true );
405 myApplyBtn->setEnabled( true );
412 //=======================================================================
413 // name : SMESHGUI_SingleEditDlg::onDeactivate
414 // Purpose : SLOT called when dialog must be deativated
415 //=======================================================================
416 void SMESHGUI_SingleEditDlg::onDeactivate()
421 //=======================================================================
422 // name : SMESHGUI_SingleEditDlg::enterEvent
423 // Purpose : Event filter
424 //=======================================================================
425 void SMESHGUI_SingleEditDlg::enterEvent( QEvent* )
427 if ( !isEnabled() ) {
428 SMESHGUI::GetSMESHGUI()->EmitSignalDeactivateDialog();
429 // set selection mode
430 QAD_Application::getDesktop()->SetSelectionMode( EdgeOfCellSelection, true );
436 //=================================================================================
437 // function : closeEvent()
439 //=================================================================================
440 void SMESHGUI_SingleEditDlg::closeEvent( QCloseEvent* e )
444 //=======================================================================
445 //function : hideEvent
446 //purpose : caused by ESC key
447 //=======================================================================
449 void SMESHGUI_SingleEditDlg::hideEvent ( QHideEvent * e )
451 if ( !isMinimized() )
455 //=================================================================================
456 // function : onApply
457 // purpose : SLOT. Called when apply button is pressed
458 //=================================================================================
459 bool SMESHGUI_SingleEditDlg::onApply()
461 if (SMESHGUI::GetSMESHGUI()->ActiveStudyLocked())
463 // verify validity of input data
464 if ( !isValid( true ) )
467 // get mesh, actor and nodes
468 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO( mySelection->firstIObject() );
470 if ( aMesh->_is_nil() )
472 QMessageBox::information( SMESHGUI::GetSMESHGUI()->GetDesktop(),
473 tr( "SMESH_ERROR" ), tr( "SMESHG_NO_MESH" ), QMessageBox::Ok );
477 SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
478 int anId1= 0, anId2 = 0;
479 if ( aMeshEditor->_is_nil() || !getNodeIds( myEdge->text(), anId1, anId2 ) )
483 bool aResult = process( aMeshEditor.in(), anId1, anId2 );
488 Handle(SALOME_InteractiveObject) anIO = mySelection->firstIObject();
489 mySelection->ClearIObjects();
491 mySelection->AddIObject( anIO, false );
498 Class : SMESHGUI_TrianglesInversionDlg
499 Description : Inversion of the diagonal of a pseudo-quadrangle formed by
500 2 neighboring triangles with 1 common edge
503 SMESHGUI_TrianglesInversionDlg::SMESHGUI_TrianglesInversionDlg( QWidget* theParent,
504 SALOME_Selection* theSelection,
505 const char* theName )
506 : SMESHGUI_SingleEditDlg( theParent, theSelection, theName )
508 setCaption( tr( "CAPTION" ) );
511 SMESHGUI_TrianglesInversionDlg::~SMESHGUI_TrianglesInversionDlg()
515 bool SMESHGUI_TrianglesInversionDlg::process(
516 SMESH::SMESH_MeshEditor_ptr theMeshEditor, const int theId1, const int theId2 )
518 return theMeshEditor->InverseDiag( theId1, theId2 );
522 Class : SMESHGUI_UnionOfTwoTrianglesDlg
523 Description : Construction of a quadrangle by deletion of the
524 common border of 2 neighboring triangles
527 SMESHGUI_UnionOfTwoTrianglesDlg::SMESHGUI_UnionOfTwoTrianglesDlg( QWidget* theParent,
528 SALOME_Selection* theSelection,
529 const char* theName )
530 : SMESHGUI_SingleEditDlg( theParent, theSelection, theName )
532 setCaption( tr( "CAPTION" ) );
535 SMESHGUI_UnionOfTwoTrianglesDlg::~SMESHGUI_UnionOfTwoTrianglesDlg()
539 bool SMESHGUI_UnionOfTwoTrianglesDlg::process(
540 SMESH::SMESH_MeshEditor_ptr theMeshEditor, const int theId1, const int theId2 )
542 return theMeshEditor->DeleteDiag( theId1, theId2 );