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);
237 mySMESHGUI->DefineDlgPosition(this, x, y);
241 // set selection mode
242 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
243 aViewWindow->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 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
266 aViewWindow->SetSelectionMode(ActorSelection);
267 //mySelectionMgr->clearSelected();
268 disconnect(mySelectionMgr, 0, this, 0);
269 disconnect(mySMESHGUI, 0, this, 0);
270 mySMESHGUI->ResetState();
274 //=======================================================================
275 //function : findTriangles()
276 //purpose : find triangles sharing theNode1-theNode2 link
277 // THIS IS A PIECE OF SMESH_MeshEditor.cxx
278 // TO DO: make it available in SMDS for ex.
279 //=======================================================================
280 static bool findTriangles (const SMDS_MeshNode * theNode1,
281 const SMDS_MeshNode * theNode2,
282 const SMDS_MeshElement*& theTria1,
283 const SMDS_MeshElement*& theTria2)
285 if (!theNode1 || !theNode2) return false;
287 theTria1 = theTria2 = 0;
289 set< const SMDS_MeshElement* > emap;
290 SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator();
292 const SMDS_MeshElement* elem = it->next();
293 if (elem->GetType() == SMDSAbs_Face && elem->NbNodes() == 3)
296 it = theNode2->GetInverseElementIterator();
298 const SMDS_MeshElement* elem = it->next();
299 if (elem->GetType() == SMDSAbs_Face &&
300 emap.find(elem) != emap.end())
308 return (theTria1 && theTria2);
311 //=======================================================================
312 //function : onTextChange()
314 //=======================================================================
315 void SMESHGUI_SingleEditDlg::onTextChange (const QString& theNewText)
319 myOkBtn->setEnabled(false);
320 myApplyBtn->setEnabled(false);
322 // hilight entered edge
324 if(SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh()){
325 myBusy = true; // block onSelectionDone()
326 Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
329 mySelectionMgr->setSelectedObjects(aList,false);
331 TColStd_IndexedMapOfInteger selectedIndices;
332 TColStd_MapOfInteger newIndices;
333 mySelector->GetIndex(anIO,selectedIndices);
336 QStringList aListId = QStringList::split("-", theNewText, false);
337 if (aListId.count() != 2)
342 const SMDS_MeshNode* a2Nodes[2];
343 for (i = 0; i < aListId.count(); i++) {
344 if(const SMDS_MeshNode *aNode = aMesh->FindNode(aListId[ i ].toInt()))
345 a2Nodes[ i ] = aNode;
350 // find a triangle and an edge nb
351 const SMDS_MeshElement* tria[2];
352 allOk &= a2Nodes[0] != a2Nodes[1] && findTriangles(a2Nodes[0],a2Nodes[1],tria[0],tria[1]);
353 myBusy = true; // block onSelectionDone()
356 newIndices.Add(tria[0]->GetID());
358 const SMDS_MeshNode* a3Nodes [3];
359 SMDS_ElemIteratorPtr it;
361 for (i = 0, it = tria[0]->nodesIterator(); it->more(); i++) {
362 a3Nodes[ i ] = static_cast<const SMDS_MeshNode*>(it->next());
364 allOk = (a3Nodes[ i ] == a2Nodes[ 0 ] && a3Nodes[ i - 1] == a2Nodes[ 1 ]) ||
365 (a3Nodes[ i ] == a2Nodes[ 1 ] && a3Nodes[ i - 1] == a2Nodes[ 0 ]);
372 newIndices.Add(-edgeInd-1);
374 myOkBtn->setEnabled(true);
375 myApplyBtn->setEnabled(true);
377 mySelector->AddOrRemoveIndex(anIO,newIndices, false);
378 SMESH::GetViewWindow(mySMESHGUI)->highlight( anIO, true, true );
385 //=======================================================================
386 // name : onSelectionDone()
387 // Purpose : SLOT called when selection changed
388 //=======================================================================
389 void SMESHGUI_SingleEditDlg::onSelectionDone()
393 int anId1 = 0, anId2 = 0;
395 myOkBtn->setEnabled(false);
396 myApplyBtn->setEnabled(false);
399 mySelectionMgr->selectedObjects(aList);
401 if (aList.Extent() != 1) {
406 Handle(SALOME_InteractiveObject) anIO = aList.First();
407 myActor = SMESH::FindActorByEntry(anIO->getEntry());
409 TVisualObjPtr aVisualObj = myActor->GetObject();
410 if(SMDS_Mesh* aMesh = aVisualObj->GetMesh())
412 const SMDS_MeshElement* tria[2];
413 if( SMESH::GetEdgeNodes( mySelector, aVisualObj, anId1, anId2 ) >= 1 &&
414 findTriangles( aMesh->FindNode( anId1 ), aMesh->FindNode( anId2 ), tria[0],tria[1] ) )
416 QString aText = QString("%1-%2").arg(anId1).arg(anId2);
418 myEdge->setText(aText);
421 myOkBtn->setEnabled(true);
422 myApplyBtn->setEnabled(true);
432 //=======================================================================
433 // name : onDeactivate()
434 // Purpose : SLOT called when dialog must be deativated
435 //=======================================================================
436 void SMESHGUI_SingleEditDlg::onDeactivate()
441 //=======================================================================
442 // name : enterEvent()
443 // Purpose : Event filter
444 //=======================================================================
445 void SMESHGUI_SingleEditDlg::enterEvent (QEvent*)
448 mySMESHGUI->EmitSignalDeactivateDialog();
449 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
450 aViewWindow->SetSelectionMode(EdgeOfCellSelection);
455 //=================================================================================
456 // function : closeEvent()
458 //=================================================================================
459 void SMESHGUI_SingleEditDlg::closeEvent (QCloseEvent*)
464 //=======================================================================
465 //function : hideEvent()
466 //purpose : caused by ESC key
467 //=======================================================================
468 void SMESHGUI_SingleEditDlg::hideEvent (QHideEvent*)
474 //=================================================================================
475 // function : onApply()
476 // purpose : SLOT. Called when apply button is pressed
477 //=================================================================================
478 bool SMESHGUI_SingleEditDlg::onApply()
480 if (mySMESHGUI->isActiveStudyLocked())
482 // verify validity of input data
486 // get mesh, actor and nodes
488 mySelectionMgr->selectedObjects(aList);
490 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(aList.First());
492 if (aMesh->_is_nil()) {
493 SUIT_MessageBox::info1(SMESH::GetDesktop(mySMESHGUI),
495 tr("SMESHG_NO_MESH"),
500 SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
501 int anId1= 0, anId2 = 0;
502 if (aMeshEditor->_is_nil() || !getNodeIds(myEdge->text(), anId1, anId2))
506 bool aResult = process(aMeshEditor.in(), anId1, anId2);
510 mySelector->ClearIndex();
511 mySelectionMgr->setSelectedObjects(aList, false);
520 * Class : SMESHGUI_TrianglesInversionDlg
521 * Description : Inversion of the diagonal of a pseudo-quadrangle formed by
522 * 2 neighboring triangles with 1 common edge
525 SMESHGUI_TrianglesInversionDlg
526 ::SMESHGUI_TrianglesInversionDlg(SMESHGUI* theModule,
528 : SMESHGUI_SingleEditDlg(theModule,theName)
530 setCaption(tr("CAPTION"));
533 SMESHGUI_TrianglesInversionDlg::~SMESHGUI_TrianglesInversionDlg()
537 bool SMESHGUI_TrianglesInversionDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
538 const int theId1, const int theId2)
540 return theMeshEditor->InverseDiag(theId1, theId2);
544 * Class : SMESHGUI_UnionOfTwoTrianglesDlg
545 * Description : Construction of a quadrangle by deletion of the
546 * common border of 2 neighboring triangles
549 SMESHGUI_UnionOfTwoTrianglesDlg
550 ::SMESHGUI_UnionOfTwoTrianglesDlg(SMESHGUI* theModule,
552 : SMESHGUI_SingleEditDlg(theModule,theName)
554 setCaption(tr("CAPTION"));
557 SMESHGUI_UnionOfTwoTrianglesDlg::~SMESHGUI_UnionOfTwoTrianglesDlg()
561 bool SMESHGUI_UnionOfTwoTrianglesDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
562 const int theId1, const int theId2)
564 return theMeshEditor->DeleteDiag(theId1, theId2);