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 "SMESH_Actor.h"
38 #include "SMDS_Mesh.hxx"
40 #include "SALOME_Selection.h"
41 #include "utilities.h"
45 #include <qlineedit.h>
46 #include <qpushbutton.h>
47 #include <qgroupbox.h>
49 #include <qmessagebox.h>
50 #include <qvalidator.h>
58 Class : SMESHGUI_DiagValidator
59 Description : validate munual input of edge like "id1-id2"
61 class SMESHGUI_DiagValidator: public QValidator
65 SMESHGUI_DiagValidator(QWidget * parent, const char * name = 0):
66 QValidator(parent,name) {}
68 State validate ( QString & text, int & pos) const
70 text.stripWhiteSpace();
71 text.replace( QRegExp("[^0-9]+"), "-" );
74 int ind = text.find( QRegExp("-[0-9]+-"));
75 if ( ind > 0 ) { // leave only two ids
76 ind = text.find( '-', ind + 1 );
80 if ( pos > text.length() )
87 Class : SMESHGUI_SingleEditDlg
88 Description : Inversion of the diagonal of a pseudo-quadrangle formed by
89 2 neighboring triangles with 1 common edge
92 //=======================================================================
93 // name : SMESHGUI_SingleEditDlg::SMESHGUI_SingleEditDlg
94 // Purpose : Constructor
95 //=======================================================================
96 SMESHGUI_SingleEditDlg::SMESHGUI_SingleEditDlg( QWidget* theParent,
97 SALOME_Selection* theSelection,
99 : QDialog( theParent, theName, false,
100 WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu )
102 //setCaption( tr( "CAPTION" ) );
104 QVBoxLayout* aDlgLay = new QVBoxLayout( this, MARGIN, SPACING );
106 QFrame* aMainFrame = createMainFrame ( this );
107 QFrame* aBtnFrame = createButtonFrame( this );
109 aDlgLay->addWidget( aMainFrame );
110 aDlgLay->addWidget( aBtnFrame );
112 aDlgLay->setStretchFactor( aMainFrame, 1 );
114 Init( theSelection ) ;
117 //=======================================================================
118 // name : SMESHGUI_SingleEditDlg::createMainFrame
119 // Purpose : Create frame containing dialog's input fields
120 //=======================================================================
121 QFrame* SMESHGUI_SingleEditDlg::createMainFrame( QWidget* theParent )
123 QGroupBox* aMainGrp = new QGroupBox( 1, Qt::Vertical, tr( "EDGE_BETWEEN" ), theParent );
125 QPixmap aPix( QAD_Desktop::getResourceManager()->loadPixmap( "SMESH",tr( "ICON_SELECT" ) ) );
127 new QLabel( tr( "SMESH_EDGE" ), aMainGrp );
128 ( new QPushButton( aMainGrp ) )->setPixmap( aPix );
129 myEdge = new QLineEdit( aMainGrp );
130 myEdge->setValidator( new SMESHGUI_DiagValidator( this, "validator" ));
135 //=======================================================================
136 // name : SMESHGUI_SingleEditDlg::createButtonFrame
137 // Purpose : Create frame containing buttons
138 //=======================================================================
139 QFrame* SMESHGUI_SingleEditDlg::createButtonFrame( QWidget* theParent )
141 QFrame* aFrame = new QFrame( theParent );
142 aFrame->setFrameStyle( QFrame::Box | QFrame::Sunken );
144 myOkBtn = new QPushButton( tr( "SMESH_BUT_OK" ), aFrame );
145 myApplyBtn = new QPushButton( tr( "SMESH_BUT_APPLY" ), aFrame );
146 myCloseBtn = new QPushButton( tr( "SMESH_BUT_CLOSE" ), aFrame );
148 QSpacerItem* aSpacer = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
150 QHBoxLayout* aLay = new QHBoxLayout( aFrame, MARGIN, SPACING );
152 aLay->addWidget( myOkBtn );
153 aLay->addWidget( myApplyBtn );
154 aLay->addItem( aSpacer);
155 aLay->addWidget( myCloseBtn );
160 //=======================================================================
161 // name : SMESHGUI_SingleEditDlg::isValid
162 // Purpose : Verify validity of input data
163 //=======================================================================
164 bool SMESHGUI_SingleEditDlg::isValid( const bool theMess ) const
167 return getNodeIds( myEdge->text(), id1, id2 );
170 //=======================================================================
171 // name : SMESHGUI_SingleEditDlg::getNodeIds
172 // Purpose : Retrieve node ids from string
173 //=======================================================================
174 bool SMESHGUI_SingleEditDlg::getNodeIds( const QString& theStr, int& theId1, int& theId2 ) const
176 if ( !theStr.contains( '-' ) )
180 QString str1 = theStr.section( '-', 0, 0, QString::SectionSkipEmpty );
181 QString str2 = theStr.section( '-', 1, 1, QString::SectionSkipEmpty );
182 theId1 = str1.toInt( &ok1 );
183 theId2 = str2.toInt( &ok2 );
188 //=======================================================================
189 // name : SMESHGUI_SingleEditDlg::~SMESHGUI_SingleEditDlg
190 // Purpose : Destructor
191 //=======================================================================
192 SMESHGUI_SingleEditDlg::~SMESHGUI_SingleEditDlg()
196 //=======================================================================
197 // name : SMESHGUI_SingleEditDlg::Init
198 // Purpose : Init dialog fields, connect signals and slots, show dialog
199 //=======================================================================
200 void SMESHGUI_SingleEditDlg::Init( SALOME_Selection* theSelection )
202 mySelection = theSelection;
203 SMESHGUI* aSMESHGUI = SMESHGUI::GetSMESHGUI();
204 aSMESHGUI->SetActiveDialogBox( ( QDialog* )this ) ;
209 connect( myOkBtn, SIGNAL( clicked() ), SLOT( onOk() ) );
210 connect( myCloseBtn, SIGNAL( clicked() ), SLOT( onClose() ) ) ;
211 connect( myApplyBtn, SIGNAL( clicked() ), SLOT( onApply() ) );
213 // selection and SMESHGUI
214 connect( mySelection, SIGNAL( currentSelectionChanged() ), SLOT( onSelectionDone() ) );
215 connect( aSMESHGUI, SIGNAL( SignalDeactivateActiveDialog() ), SLOT( onDeactivate() ) );
216 connect( aSMESHGUI, SIGNAL( SignalCloseAllDialogs() ), SLOT( onClose() ) );
217 connect( myEdge, SIGNAL( textChanged(const QString&)), SLOT( onTextChange(const QString&)));
219 myOkBtn->setEnabled( false );
220 myApplyBtn->setEnabled( false );
224 aSMESHGUI->DefineDlgPosition( this, x, y );
228 // set selection mode
229 QAD_Application::getDesktop()->SetSelectionMode( EdgeOfCellSelection, true );
236 //=======================================================================
237 // name : SMESHGUI_SingleEditDlg::onOk
238 // Purpose : SLOT called when "Ok" button pressed.
239 // Assign filters VTK viewer and close dialog
240 //=======================================================================
241 void SMESHGUI_SingleEditDlg::onOk()
247 //=======================================================================
248 // name : SMESHGUI_SingleEditDlg::onClose
249 // Purpose : SLOT called when "Close" button pressed. Close dialog
250 //=======================================================================
251 void SMESHGUI_SingleEditDlg::onClose()
253 QAD_Application::getDesktop()->SetSelectionMode( ActorSelection );
254 mySelection->ClearIObjects();
255 disconnect( mySelection, 0, this, 0 );
256 disconnect( SMESHGUI::GetSMESHGUI(), 0, this, 0 );
257 SMESHGUI::GetSMESHGUI()->ResetState() ;
261 //=======================================================================
262 //function : findTriangles
263 //purpose : find triangles sharing theNode1-theNode2 link
264 // THIS IS A PIECE OF SMESH_MeshEditor.cxx
265 // TO DO: make it available in SMDS for ex.
266 //=======================================================================
268 static bool findTriangles(const SMDS_MeshNode * theNode1,
269 const SMDS_MeshNode * theNode2,
270 const SMDS_MeshElement*& theTria1,
271 const SMDS_MeshElement*& theTria2)
273 if ( !theNode1 || !theNode2 ) return false;
275 theTria1 = theTria2 = 0;
277 set< const SMDS_MeshElement* > emap;
278 SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator();
280 const SMDS_MeshElement* elem = it->next();
281 if ( elem->GetType() == SMDSAbs_Face && elem->NbNodes() == 3 )
284 it = theNode2->GetInverseElementIterator();
286 const SMDS_MeshElement* elem = it->next();
287 if ( elem->GetType() == SMDSAbs_Face &&
288 emap.find( elem ) != emap.end() )
296 return ( theTria1 && theTria2 );
299 //=======================================================================
300 //function : onTextChange
302 //=======================================================================
304 void SMESHGUI_SingleEditDlg::onTextChange( const QString& theNewText )
306 if ( myBusy ) return;
308 myOkBtn->setEnabled( false );
309 myApplyBtn->setEnabled( false );
311 // hilight entered edge
312 SMDS_Mesh* aMesh = 0;
314 aMesh = myActor->GetObject()->GetMesh();
317 myBusy = true; // block onSelectionDone()
318 mySelection->ClearIObjects();
319 mySelection->AddIObject( myActor->getIO() );
322 QStringList aListId = QStringList::split( "-", theNewText, false);
323 if ( aListId.count() != 2 )
325 const SMDS_MeshNode* a2Nodes[2];
328 for ( i = 0; i < aListId.count(); i++ ) {
329 const SMDS_MeshNode * n = aMesh->FindNode( aListId[ i ].toInt() );
336 // find a triangle and an edge nb
337 const SMDS_MeshElement* tria[2];
339 a2Nodes[0] != a2Nodes[1] &&
340 findTriangles( a2Nodes[0],
344 myBusy = true; // block onSelectionDone()
345 mySelection->AddOrRemoveIndex (myActor->getIO(), tria[0]->GetID(), true, false);
347 const SMDS_MeshNode* a3Nodes [3];
348 SMDS_ElemIteratorPtr it;
350 for (i = 0, it = tria[0]->nodesIterator(); it->more(); i++ ) {
351 a3Nodes[ i ] = static_cast<const SMDS_MeshNode*>( it->next() );
353 if (( a3Nodes[ i ] == a2Nodes[ 0 ] && a3Nodes[ i - 1] == a2Nodes[ 1 ] ) ||
354 ( a3Nodes[ i ] == a2Nodes[ 1 ] && a3Nodes[ i - 1] == a2Nodes[ 0 ] ) ) {
360 mySelection->AddOrRemoveIndex( myActor->getIO(), -edgeInd-1, true, true );
363 myOkBtn->setEnabled( true );
364 myApplyBtn->setEnabled( true );
368 //=======================================================================
369 // name : SMESHGUI_SingleEditDlg::onSelectionDone
370 // Purpose : SLOT called when selection changed
371 //=======================================================================
372 void SMESHGUI_SingleEditDlg::onSelectionDone()
374 if ( myBusy ) return;
376 int anId1 = 0, anId2 = 0;
378 myOkBtn->setEnabled( false );
379 myApplyBtn->setEnabled( false );
381 if ( mySelection->IObjectCount() != 1 )
387 myActor = SMESH::FindActorByEntry( mySelection->firstIObject()->getEntry() );
388 SMDS_Mesh* aMesh = 0;
390 aMesh = myActor->GetObject()->GetMesh();
394 if (SMESH::GetEdgeNodes( mySelection, anId1, anId2 ) >= 1 ) {
395 QString aText = QString( "%1-%2" ).arg( anId1 ).arg( anId2 );
397 myEdge->setText( aText );
400 const SMDS_MeshElement* tria[2];
401 if ( findTriangles( aMesh->FindNode( anId1 ), aMesh->FindNode( anId2 ), tria[0],tria[1]))
403 myOkBtn->setEnabled( true );
404 myApplyBtn->setEnabled( true );
411 //=======================================================================
412 // name : SMESHGUI_SingleEditDlg::onDeactivate
413 // Purpose : SLOT called when dialog must be deativated
414 //=======================================================================
415 void SMESHGUI_SingleEditDlg::onDeactivate()
420 //=======================================================================
421 // name : SMESHGUI_SingleEditDlg::enterEvent
422 // Purpose : Event filter
423 //=======================================================================
424 void SMESHGUI_SingleEditDlg::enterEvent( QEvent* )
426 if ( !isEnabled() ) {
427 SMESHGUI::GetSMESHGUI()->EmitSignalDeactivateDialog();
428 // set selection mode
429 QAD_Application::getDesktop()->SetSelectionMode( EdgeOfCellSelection, true );
435 //=================================================================================
436 // function : closeEvent()
438 //=================================================================================
439 void SMESHGUI_SingleEditDlg::closeEvent( QCloseEvent* e )
443 //=======================================================================
444 //function : hideEvent
445 //purpose : caused by ESC key
446 //=======================================================================
448 void SMESHGUI_SingleEditDlg::hideEvent ( QHideEvent * e )
450 if ( !isMinimized() )
454 //=================================================================================
455 // function : onApply
456 // purpose : SLOT. Called when apply button is pressed
457 //=================================================================================
458 bool SMESHGUI_SingleEditDlg::onApply()
460 if (SMESHGUI::GetSMESHGUI()->ActiveStudyLocked())
462 // verify validity of input data
463 if ( !isValid( true ) )
466 // get mesh, actor and nodes
467 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO( mySelection->firstIObject() );
469 if ( aMesh->_is_nil() )
471 QMessageBox::information( SMESHGUI::GetSMESHGUI()->GetDesktop(),
472 tr( "SMESH_ERROR" ), tr( "SMESHG_NO_MESH" ), QMessageBox::Ok );
476 SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
477 int anId1= 0, anId2 = 0;
478 if ( aMeshEditor->_is_nil() || !getNodeIds( myEdge->text(), anId1, anId2 ) )
482 bool aResult = process( aMeshEditor.in(), anId1, anId2 );
487 Handle(SALOME_InteractiveObject) anIO = mySelection->firstIObject();
488 mySelection->ClearIObjects();
490 mySelection->AddIObject( anIO, false );
497 Class : SMESHGUI_TrianglesInversionDlg
498 Description : Inversion of the diagonal of a pseudo-quadrangle formed by
499 2 neighboring triangles with 1 common edge
502 SMESHGUI_TrianglesInversionDlg::SMESHGUI_TrianglesInversionDlg( QWidget* theParent,
503 SALOME_Selection* theSelection,
504 const char* theName )
505 : SMESHGUI_SingleEditDlg( theParent, theSelection, theName )
507 setCaption( tr( "CAPTION" ) );
510 SMESHGUI_TrianglesInversionDlg::~SMESHGUI_TrianglesInversionDlg()
514 bool SMESHGUI_TrianglesInversionDlg::process(
515 SMESH::SMESH_MeshEditor_ptr theMeshEditor, const int theId1, const int theId2 )
517 return theMeshEditor->InverseDiag( theId1, theId2 );
521 Class : SMESHGUI_UnionOfTwoTrianglesDlg
522 Description : Construction of a quadrangle by deletion of the
523 common border of 2 neighboring triangles
526 SMESHGUI_UnionOfTwoTrianglesDlg::SMESHGUI_UnionOfTwoTrianglesDlg( QWidget* theParent,
527 SALOME_Selection* theSelection,
528 const char* theName )
529 : SMESHGUI_SingleEditDlg( theParent, theSelection, theName )
531 setCaption( tr( "CAPTION" ) );
534 SMESHGUI_UnionOfTwoTrianglesDlg::~SMESHGUI_UnionOfTwoTrianglesDlg()
538 bool SMESHGUI_UnionOfTwoTrianglesDlg::process(
539 SMESH::SMESH_MeshEditor_ptr theMeshEditor, const int theId1, const int theId2 )
541 return theMeshEditor->DeleteDiag( theId1, theId2 );