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 "SalomeApp_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 myViewWindow(SMESH::GetViewWindow(theModule)),
117 mySMESHGUI(theModule)
119 QVBoxLayout* aDlgLay = new QVBoxLayout(this, MARGIN, SPACING);
121 QFrame* aMainFrame = createMainFrame (this);
122 QFrame* aBtnFrame = createButtonFrame(this);
124 aDlgLay->addWidget(aMainFrame);
125 aDlgLay->addWidget(aBtnFrame);
127 aDlgLay->setStretchFactor(aMainFrame, 1);
132 //=======================================================================
133 // name : createMainFrame()
134 // Purpose : Create frame containing dialog's input fields
135 //=======================================================================
136 QFrame* SMESHGUI_SingleEditDlg::createMainFrame (QWidget* theParent)
138 QGroupBox* aMainGrp = new QGroupBox(1, Qt::Vertical, tr("EDGE_BETWEEN"), theParent);
140 QPixmap aPix (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
142 new QLabel(tr("SMESH_EDGE"), aMainGrp);
143 (new QPushButton(aMainGrp))->setPixmap(aPix);
144 myEdge = new QLineEdit(aMainGrp);
145 myEdge->setValidator(new SMESHGUI_DiagValidator(this, "validator"));
150 //=======================================================================
151 // name : createButtonFrame()
152 // Purpose : Create frame containing buttons
153 //=======================================================================
154 QFrame* SMESHGUI_SingleEditDlg::createButtonFrame (QWidget* theParent)
156 QFrame* aFrame = new QFrame(theParent);
157 aFrame->setFrameStyle(QFrame::Box | QFrame::Sunken);
159 myOkBtn = new QPushButton(tr("SMESH_BUT_OK" ), aFrame);
160 myApplyBtn = new QPushButton(tr("SMESH_BUT_APPLY"), aFrame);
161 myCloseBtn = new QPushButton(tr("SMESH_BUT_CLOSE"), aFrame);
163 QSpacerItem* aSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
165 QHBoxLayout* aLay = new QHBoxLayout(aFrame, MARGIN, SPACING);
167 aLay->addWidget(myOkBtn);
168 aLay->addWidget(myApplyBtn);
169 aLay->addItem(aSpacer);
170 aLay->addWidget(myCloseBtn);
175 //=======================================================================
177 // Purpose : Verify validity of input data
178 //=======================================================================
179 bool SMESHGUI_SingleEditDlg::isValid (const bool theMess) const
182 return getNodeIds(myEdge->text(), id1, id2);
185 //=======================================================================
186 // name : getNodeIds()
187 // Purpose : Retrieve node ids from string
188 //=======================================================================
189 bool SMESHGUI_SingleEditDlg::getNodeIds (const QString& theStr,
190 int& theId1, int& theId2) const
192 if (!theStr.contains('-'))
196 QString str1 = theStr.section('-', 0, 0, QString::SectionSkipEmpty);
197 QString str2 = theStr.section('-', 1, 1, QString::SectionSkipEmpty);
198 theId1 = str1.toInt(&ok1);
199 theId2 = str2.toInt(&ok2);
204 //=======================================================================
205 // name : ~SMESHGUI_SingleEditDlg()
206 // Purpose : Destructor
207 //=======================================================================
208 SMESHGUI_SingleEditDlg::~SMESHGUI_SingleEditDlg()
212 //=======================================================================
214 // Purpose : Init dialog fields, connect signals and slots, show dialog
215 //=======================================================================
216 void SMESHGUI_SingleEditDlg::Init()
218 mySMESHGUI->SetActiveDialogBox((QDialog*)this);
223 connect(myOkBtn, SIGNAL(clicked()), SLOT(onOk()));
224 connect(myCloseBtn, SIGNAL(clicked()), SLOT(onClose()));
225 connect(myApplyBtn, SIGNAL(clicked()), SLOT(onApply()));
227 // selection and SMESHGUI
228 connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
229 connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
230 connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(onClose()));
231 connect(myEdge, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
233 myOkBtn->setEnabled(false);
234 myApplyBtn->setEnabled(false);
238 mySMESHGUI->DefineDlgPosition(this, x, y);
242 // set selection mode
243 myViewWindow->SetSelectionMode(EdgeOfCellSelection);
248 //=======================================================================
250 // Purpose : SLOT called when "Ok" button pressed.
251 // Assign filters VTK viewer and close dialog
252 //=======================================================================
253 void SMESHGUI_SingleEditDlg::onOk()
259 //=======================================================================
261 // Purpose : SLOT called when "Close" button pressed. Close dialog
262 //=======================================================================
263 void SMESHGUI_SingleEditDlg::onClose()
265 myViewWindow->SetSelectionMode(ActorSelection);
266 mySelectionMgr->clearSelected();
267 disconnect(mySelectionMgr, 0, this, 0);
268 disconnect(mySMESHGUI, 0, this, 0);
269 mySMESHGUI->ResetState();
273 //=======================================================================
274 //function : findTriangles()
275 //purpose : find triangles sharing theNode1-theNode2 link
276 // THIS IS A PIECE OF SMESH_MeshEditor.cxx
277 // TO DO: make it available in SMDS for ex.
278 //=======================================================================
279 static bool findTriangles (const SMDS_MeshNode * theNode1,
280 const SMDS_MeshNode * theNode2,
281 const SMDS_MeshElement*& theTria1,
282 const SMDS_MeshElement*& theTria2)
284 if (!theNode1 || !theNode2) return false;
286 theTria1 = theTria2 = 0;
288 set< const SMDS_MeshElement* > emap;
289 SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator();
291 const SMDS_MeshElement* elem = it->next();
292 if (elem->GetType() == SMDSAbs_Face && elem->NbNodes() == 3)
295 it = theNode2->GetInverseElementIterator();
297 const SMDS_MeshElement* elem = it->next();
298 if (elem->GetType() == SMDSAbs_Face &&
299 emap.find(elem) != emap.end())
307 return (theTria1 && theTria2);
310 //=======================================================================
311 //function : onTextChange()
313 //=======================================================================
314 void SMESHGUI_SingleEditDlg::onTextChange (const QString& theNewText)
318 myOkBtn->setEnabled(false);
319 myApplyBtn->setEnabled(false);
321 // hilight entered edge
323 if(SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh()){
324 myBusy = true; // block onSelectionDone()
325 Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
328 mySelectionMgr->setSelectedObjects(aList,false);
330 TColStd_IndexedMapOfInteger selectedIndices;
331 TColStd_MapOfInteger newIndices;
332 mySelector->GetIndex(anIO,selectedIndices);
335 QStringList aListId = QStringList::split("-", theNewText, false);
336 if (aListId.count() != 2)
341 const SMDS_MeshNode* a2Nodes[2];
342 for (i = 0; i < aListId.count(); i++) {
343 if(const SMDS_MeshNode *aNode = aMesh->FindNode(aListId[ i ].toInt()))
344 a2Nodes[ i ] = aNode;
349 // find a triangle and an edge nb
350 const SMDS_MeshElement* tria[2];
351 allOk &= a2Nodes[0] != a2Nodes[1] && findTriangles(a2Nodes[0],a2Nodes[1],tria[0],tria[1]);
353 myBusy = true; // block onSelectionDone()
354 newIndices.Add(tria[0]->GetID());
355 mySelector->AddOrRemoveIndex(anIO,newIndices, true);
357 const SMDS_MeshNode* a3Nodes [3];
358 SMDS_ElemIteratorPtr it;
360 for (i = 0, it = tria[0]->nodesIterator(); it->more(); i++) {
361 a3Nodes[ i ] = static_cast<const SMDS_MeshNode*>(it->next());
363 allOk = (a3Nodes[ i ] == a2Nodes[ 0 ] && a3Nodes[ i - 1] == a2Nodes[ 1 ]) ||
364 (a3Nodes[ i ] == a2Nodes[ 1 ] && a3Nodes[ i - 1] == a2Nodes[ 0 ]);
373 newIndices.Add(-edgeInd-1);
374 mySelector->AddOrRemoveIndex(anIO,newIndices,true);
377 myOkBtn->setEnabled(true);
378 myApplyBtn->setEnabled(true);
384 //=======================================================================
385 // name : onSelectionDone()
386 // Purpose : SLOT called when selection changed
387 //=======================================================================
388 void SMESHGUI_SingleEditDlg::onSelectionDone()
392 int anId1 = 0, anId2 = 0;
394 myOkBtn->setEnabled(false);
395 myApplyBtn->setEnabled(false);
398 mySelectionMgr->selectedObjects(aList);
400 if (aList.Extent() != 1) {
405 Handle(SALOME_InteractiveObject) anIO = aList.First();
406 myActor = SMESH::FindActorByEntry(anIO->getEntry());
408 TVisualObjPtr aVisualObj = myActor->GetObject();
409 if(SMDS_Mesh* aMesh = aVisualObj->GetMesh()){
410 if(SMESH::GetEdgeNodes(mySelector, aVisualObj, anId1, anId2) >= 1){
411 QString aText = QString("%1-%2").arg(anId1).arg(anId2);
413 myEdge->setText(aText);
416 const SMDS_MeshElement* tria[2];
417 if (findTriangles(aMesh->FindNode(anId1), aMesh->FindNode(anId2), tria[0],tria[1])) {
418 myOkBtn->setEnabled(true);
419 myApplyBtn->setEnabled(true);
428 //=======================================================================
429 // name : onDeactivate()
430 // Purpose : SLOT called when dialog must be deativated
431 //=======================================================================
432 void SMESHGUI_SingleEditDlg::onDeactivate()
437 //=======================================================================
438 // name : enterEvent()
439 // Purpose : Event filter
440 //=======================================================================
441 void SMESHGUI_SingleEditDlg::enterEvent (QEvent*)
444 mySMESHGUI->EmitSignalDeactivateDialog();
445 myViewWindow->SetSelectionMode(EdgeOfCellSelection);
450 //=================================================================================
451 // function : closeEvent()
453 //=================================================================================
454 void SMESHGUI_SingleEditDlg::closeEvent (QCloseEvent*)
459 //=======================================================================
460 //function : hideEvent()
461 //purpose : caused by ESC key
462 //=======================================================================
463 void SMESHGUI_SingleEditDlg::hideEvent (QHideEvent*)
469 //=================================================================================
470 // function : onApply()
471 // purpose : SLOT. Called when apply button is pressed
472 //=================================================================================
473 bool SMESHGUI_SingleEditDlg::onApply()
475 if (mySMESHGUI->isActiveStudyLocked())
477 // verify validity of input data
481 // get mesh, actor and nodes
483 mySelectionMgr->selectedObjects(aList);
485 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(aList.First());
487 if (aMesh->_is_nil()) {
488 SUIT_MessageBox::info1(SMESH::GetDesktop(mySMESHGUI),
490 tr("SMESHG_NO_MESH"),
495 SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
496 int anId1= 0, anId2 = 0;
497 if (aMeshEditor->_is_nil() || !getNodeIds(myEdge->text(), anId1, anId2))
501 bool aResult = process(aMeshEditor.in(), anId1, anId2);
505 mySelectionMgr->setSelectedObjects(aList, false);
513 * Class : SMESHGUI_TrianglesInversionDlg
514 * Description : Inversion of the diagonal of a pseudo-quadrangle formed by
515 * 2 neighboring triangles with 1 common edge
518 SMESHGUI_TrianglesInversionDlg
519 ::SMESHGUI_TrianglesInversionDlg(SMESHGUI* theModule,
521 : SMESHGUI_SingleEditDlg(theModule,theName)
523 setCaption(tr("CAPTION"));
526 SMESHGUI_TrianglesInversionDlg::~SMESHGUI_TrianglesInversionDlg()
530 bool SMESHGUI_TrianglesInversionDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
531 const int theId1, const int theId2)
533 return theMeshEditor->InverseDiag(theId1, theId2);
537 * Class : SMESHGUI_UnionOfTwoTrianglesDlg
538 * Description : Construction of a quadrangle by deletion of the
539 * common border of 2 neighboring triangles
542 SMESHGUI_UnionOfTwoTrianglesDlg
543 ::SMESHGUI_UnionOfTwoTrianglesDlg(SMESHGUI* theModule,
545 : SMESHGUI_SingleEditDlg(theModule,theName)
547 setCaption(tr("CAPTION"));
550 SMESHGUI_UnionOfTwoTrianglesDlg::~SMESHGUI_UnionOfTwoTrianglesDlg()
554 bool SMESHGUI_UnionOfTwoTrianglesDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
555 const int theId1, const int theId2)
557 return theMeshEditor->DeleteDiag(theId1, theId2);