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"
31 #include "SMESHGUI_Utils.h"
32 #include "SMESHGUI_VTKUtils.h"
33 #include "SMESHGUI_MeshUtils.h"
34 #include "SMESHGUI_SpinBox.h"
36 #include "SMESH_Actor.h"
37 #include "SMDS_Mesh.hxx"
39 #include "LightApp_SelectionMgr.h"
40 #include "SUIT_ResourceMgr.h"
41 #include "SUIT_MessageBox.h"
42 #include "SUIT_Desktop.h"
44 #include "SVTK_Selector.h"
45 #include "SVTK_ViewWindow.h"
46 #include "SALOME_ListIO.hxx"
48 #include "utilities.h"
51 #include <TColStd_MapOfInteger.hxx>
52 #include <TColStd_IndexedMapOfInteger.hxx>
57 #include <qlineedit.h>
58 #include <qpushbutton.h>
59 #include <qgroupbox.h>
61 #include <qmessagebox.h>
62 #include <qvalidator.h>
70 * Class : SMESHGUI_DiagValidator
71 * Description : validate munual input of edge like "id1-id2"
73 class SMESHGUI_DiagValidator: public QValidator
76 SMESHGUI_DiagValidator (QWidget * parent, const char * name = 0):
77 QValidator(parent,name) {}
79 State validate (QString & text, int & pos) const
81 text.stripWhiteSpace();
82 text.replace(QRegExp("[^0-9]+"), "-");
85 int ind = text.find(QRegExp("-[0-9]+-"));
86 if (ind > 0) { // leave only two ids
87 ind = text.find('-', ind + 1);
91 if (pos > text.length())
98 * Class : SMESHGUI_SingleEditDlg
99 * Description : Inversion of the diagonal of a pseudo-quadrangle formed by
100 * 2 neighboring triangles with 1 common edge
103 //=======================================================================
104 // name : SMESHGUI_SingleEditDlg()
105 // Purpose : Constructor
106 //=======================================================================
107 SMESHGUI_SingleEditDlg
108 ::SMESHGUI_SingleEditDlg(SMESHGUI* theModule,
109 const char* theName):
110 QDialog(SMESH::GetDesktop(theModule),
113 WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
114 mySelector(SMESH::GetViewWindow(theModule)->GetSelector()),
115 mySelectionMgr(SMESH::GetSelectionMgr(theModule)),
116 mySMESHGUI(theModule)
118 QVBoxLayout* aDlgLay = new QVBoxLayout(this, MARGIN, SPACING);
120 QFrame* aMainFrame = createMainFrame (this);
121 QFrame* aBtnFrame = createButtonFrame(this);
123 aDlgLay->addWidget(aMainFrame);
124 aDlgLay->addWidget(aBtnFrame);
126 aDlgLay->setStretchFactor(aMainFrame, 1);
131 //=======================================================================
132 // name : createMainFrame()
133 // Purpose : Create frame containing dialog's input fields
134 //=======================================================================
135 QFrame* SMESHGUI_SingleEditDlg::createMainFrame (QWidget* theParent)
137 QGroupBox* aMainGrp = new QGroupBox(1, Qt::Vertical, tr("EDGE_BETWEEN"), theParent);
139 QPixmap aPix (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
141 new QLabel(tr("SMESH_EDGE"), aMainGrp);
142 (new QPushButton(aMainGrp))->setPixmap(aPix);
143 myEdge = new QLineEdit(aMainGrp);
144 myEdge->setValidator(new SMESHGUI_DiagValidator(this, "validator"));
149 //=======================================================================
150 // name : createButtonFrame()
151 // Purpose : Create frame containing buttons
152 //=======================================================================
153 QFrame* SMESHGUI_SingleEditDlg::createButtonFrame (QWidget* theParent)
155 QFrame* aFrame = new QFrame(theParent);
156 aFrame->setFrameStyle(QFrame::Box | QFrame::Sunken);
158 myOkBtn = new QPushButton(tr("SMESH_BUT_OK" ), aFrame);
159 myApplyBtn = new QPushButton(tr("SMESH_BUT_APPLY"), aFrame);
160 myCloseBtn = new QPushButton(tr("SMESH_BUT_CLOSE"), aFrame);
162 QSpacerItem* aSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
164 QHBoxLayout* aLay = new QHBoxLayout(aFrame, MARGIN, SPACING);
166 aLay->addWidget(myOkBtn);
167 aLay->addWidget(myApplyBtn);
168 aLay->addItem(aSpacer);
169 aLay->addWidget(myCloseBtn);
174 //=======================================================================
176 // Purpose : Verify validity of input data
177 //=======================================================================
178 bool SMESHGUI_SingleEditDlg::isValid (const bool theMess) const
181 return getNodeIds(myEdge->text(), id1, id2);
184 //=======================================================================
185 // name : getNodeIds()
186 // Purpose : Retrieve node ids from string
187 //=======================================================================
188 bool SMESHGUI_SingleEditDlg::getNodeIds (const QString& theStr,
189 int& theId1, int& theId2) const
191 if (!theStr.contains('-'))
195 QString str1 = theStr.section('-', 0, 0, QString::SectionSkipEmpty);
196 QString str2 = theStr.section('-', 1, 1, QString::SectionSkipEmpty);
197 theId1 = str1.toInt(&ok1);
198 theId2 = str2.toInt(&ok2);
203 //=======================================================================
204 // name : ~SMESHGUI_SingleEditDlg()
205 // Purpose : Destructor
206 //=======================================================================
207 SMESHGUI_SingleEditDlg::~SMESHGUI_SingleEditDlg()
211 //=======================================================================
213 // Purpose : Init dialog fields, connect signals and slots, show dialog
214 //=======================================================================
215 void SMESHGUI_SingleEditDlg::Init()
217 mySMESHGUI->SetActiveDialogBox((QDialog*)this);
222 connect(myOkBtn, SIGNAL(clicked()), SLOT(onOk()));
223 connect(myCloseBtn, SIGNAL(clicked()), SLOT(onClose()));
224 connect(myApplyBtn, SIGNAL(clicked()), SLOT(onApply()));
226 // selection and SMESHGUI
227 connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
228 connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
229 connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(onClose()));
230 connect(myEdge, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
232 myOkBtn->setEnabled(false);
233 myApplyBtn->setEnabled(false);
238 // set selection mode
239 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
240 aViewWindow->SetSelectionMode(EdgeOfCellSelection);
245 //=======================================================================
247 // Purpose : SLOT called when "Ok" button pressed.
248 // Assign filters VTK viewer and close dialog
249 //=======================================================================
250 void SMESHGUI_SingleEditDlg::onOk()
256 //=======================================================================
258 // Purpose : SLOT called when "Close" button pressed. Close dialog
259 //=======================================================================
260 void SMESHGUI_SingleEditDlg::onClose()
262 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
263 aViewWindow->SetSelectionMode(ActorSelection);
264 //mySelectionMgr->clearSelected();
265 disconnect(mySelectionMgr, 0, this, 0);
266 disconnect(mySMESHGUI, 0, this, 0);
267 mySMESHGUI->ResetState();
271 //=======================================================================
272 //function : findTriangles()
273 //purpose : find triangles sharing theNode1-theNode2 link
274 // THIS IS A PIECE OF SMESH_MeshEditor.cxx
275 // TO DO: make it available in SMDS for ex.
276 //=======================================================================
277 static bool findTriangles (const SMDS_MeshNode * theNode1,
278 const SMDS_MeshNode * theNode2,
279 const SMDS_MeshElement*& theTria1,
280 const SMDS_MeshElement*& theTria2)
282 if (!theNode1 || !theNode2) return false;
284 theTria1 = theTria2 = 0;
286 set< const SMDS_MeshElement* > emap;
287 SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator();
289 const SMDS_MeshElement* elem = it->next();
290 if (elem->GetType() == SMDSAbs_Face && elem->NbNodes() == 3)
293 it = theNode2->GetInverseElementIterator();
295 const SMDS_MeshElement* elem = it->next();
296 if (elem->GetType() == SMDSAbs_Face &&
297 emap.find(elem) != emap.end())
305 return (theTria1 && theTria2);
308 //=======================================================================
309 //function : onTextChange()
311 //=======================================================================
312 void SMESHGUI_SingleEditDlg::onTextChange (const QString& theNewText)
316 myOkBtn->setEnabled(false);
317 myApplyBtn->setEnabled(false);
319 // hilight entered edge
321 if(SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh()){
322 myBusy = true; // block onSelectionDone()
323 Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
326 mySelectionMgr->setSelectedObjects(aList,false);
328 TColStd_IndexedMapOfInteger selectedIndices;
329 TColStd_MapOfInteger newIndices;
330 mySelector->GetIndex(anIO,selectedIndices);
333 QStringList aListId = QStringList::split("-", theNewText, false);
334 if (aListId.count() != 2)
339 const SMDS_MeshNode* a2Nodes[2];
340 for (i = 0; i < aListId.count(); i++) {
341 if(const SMDS_MeshNode *aNode = aMesh->FindNode(aListId[ i ].toInt()))
342 a2Nodes[ i ] = aNode;
347 // find a triangle and an edge nb
348 const SMDS_MeshElement* tria[2];
349 allOk &= a2Nodes[0] != a2Nodes[1] && findTriangles(a2Nodes[0],a2Nodes[1],tria[0],tria[1]);
350 myBusy = true; // block onSelectionDone()
353 newIndices.Add(tria[0]->GetID());
355 const SMDS_MeshNode* a3Nodes [3];
356 SMDS_ElemIteratorPtr it;
358 for (i = 0, it = tria[0]->nodesIterator(); it->more(); i++) {
359 a3Nodes[ i ] = static_cast<const SMDS_MeshNode*>(it->next());
361 allOk = (a3Nodes[ i ] == a2Nodes[ 0 ] && a3Nodes[ i - 1] == a2Nodes[ 1 ]) ||
362 (a3Nodes[ i ] == a2Nodes[ 1 ] && a3Nodes[ i - 1] == a2Nodes[ 0 ]);
369 newIndices.Add(-edgeInd-1);
371 myOkBtn->setEnabled(true);
372 myApplyBtn->setEnabled(true);
374 mySelector->AddOrRemoveIndex(anIO,newIndices, false);
375 SMESH::GetViewWindow(mySMESHGUI)->highlight( anIO, true, true );
382 //=======================================================================
383 // name : onSelectionDone()
384 // Purpose : SLOT called when selection changed
385 //=======================================================================
386 void SMESHGUI_SingleEditDlg::onSelectionDone()
390 int anId1 = 0, anId2 = 0;
392 myOkBtn->setEnabled(false);
393 myApplyBtn->setEnabled(false);
396 mySelectionMgr->selectedObjects(aList);
398 if (aList.Extent() != 1) {
403 Handle(SALOME_InteractiveObject) anIO = aList.First();
404 myActor = SMESH::FindActorByEntry(anIO->getEntry());
406 TVisualObjPtr aVisualObj = myActor->GetObject();
407 if(SMDS_Mesh* aMesh = aVisualObj->GetMesh())
409 const SMDS_MeshElement* tria[2];
410 if( SMESH::GetEdgeNodes( mySelector, aVisualObj, anId1, anId2 ) >= 1 &&
411 findTriangles( aMesh->FindNode( anId1 ), aMesh->FindNode( anId2 ), tria[0],tria[1] ) )
413 QString aText = QString("%1-%2").arg(anId1).arg(anId2);
415 myEdge->setText(aText);
418 myOkBtn->setEnabled(true);
419 myApplyBtn->setEnabled(true);
429 //=======================================================================
430 // name : onDeactivate()
431 // Purpose : SLOT called when dialog must be deativated
432 //=======================================================================
433 void SMESHGUI_SingleEditDlg::onDeactivate()
438 //=======================================================================
439 // name : enterEvent()
440 // Purpose : Event filter
441 //=======================================================================
442 void SMESHGUI_SingleEditDlg::enterEvent (QEvent*)
445 mySMESHGUI->EmitSignalDeactivateDialog();
446 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
447 aViewWindow->SetSelectionMode(EdgeOfCellSelection);
452 //=================================================================================
453 // function : closeEvent()
455 //=================================================================================
456 void SMESHGUI_SingleEditDlg::closeEvent (QCloseEvent*)
461 //=======================================================================
462 //function : hideEvent()
463 //purpose : caused by ESC key
464 //=======================================================================
465 void SMESHGUI_SingleEditDlg::hideEvent (QHideEvent*)
471 //=================================================================================
472 // function : onApply()
473 // purpose : SLOT. Called when apply button is pressed
474 //=================================================================================
475 bool SMESHGUI_SingleEditDlg::onApply()
477 if (mySMESHGUI->isActiveStudyLocked())
479 // verify validity of input data
483 // get mesh, actor and nodes
485 mySelectionMgr->selectedObjects(aList);
487 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(aList.First());
489 if (aMesh->_is_nil()) {
490 SUIT_MessageBox::info1(SMESH::GetDesktop(mySMESHGUI),
492 tr("SMESHG_NO_MESH"),
497 SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
498 int anId1= 0, anId2 = 0;
499 if (aMeshEditor->_is_nil() || !getNodeIds(myEdge->text(), anId1, anId2))
503 bool aResult = process(aMeshEditor.in(), anId1, anId2);
507 mySelector->ClearIndex();
508 mySelectionMgr->setSelectedObjects(aList, false);
517 * Class : SMESHGUI_TrianglesInversionDlg
518 * Description : Inversion of the diagonal of a pseudo-quadrangle formed by
519 * 2 neighboring triangles with 1 common edge
522 SMESHGUI_TrianglesInversionDlg
523 ::SMESHGUI_TrianglesInversionDlg(SMESHGUI* theModule,
525 : SMESHGUI_SingleEditDlg(theModule,theName)
527 setCaption(tr("CAPTION"));
530 SMESHGUI_TrianglesInversionDlg::~SMESHGUI_TrianglesInversionDlg()
534 bool SMESHGUI_TrianglesInversionDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
535 const int theId1, const int theId2)
537 return theMeshEditor->InverseDiag(theId1, theId2);
541 * Class : SMESHGUI_UnionOfTwoTrianglesDlg
542 * Description : Construction of a quadrangle by deletion of the
543 * common border of 2 neighboring triangles
546 SMESHGUI_UnionOfTwoTrianglesDlg
547 ::SMESHGUI_UnionOfTwoTrianglesDlg(SMESHGUI* theModule,
549 : SMESHGUI_SingleEditDlg(theModule,theName)
551 setCaption(tr("CAPTION"));
554 SMESHGUI_UnionOfTwoTrianglesDlg::~SMESHGUI_UnionOfTwoTrianglesDlg()
558 bool SMESHGUI_UnionOfTwoTrianglesDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
559 const int theId1, const int theId2)
561 return theMeshEditor->DeleteDiag(theId1, theId2);