1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 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.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : SMESHGUI_SingleEditDlg.cxx
24 // Author : Sergey LITONIN, Open CASCADE S.A.S.
27 #include "SMESHGUI_SingleEditDlg.h"
30 #include "SMESHGUI_Utils.h"
31 #include "SMESHGUI_VTKUtils.h"
32 #include "SMESHGUI_MeshUtils.h"
34 #include <SMESH_Actor.h>
35 #include <SMDS_Mesh.hxx>
37 // SALOME GUI includes
38 #include <LightApp_SelectionMgr.h>
39 #include <LightApp_Application.h>
40 #include <SUIT_ResourceMgr.h>
41 #include <SUIT_MessageBox.h>
42 #include <SUIT_Desktop.h>
43 #include <SUIT_Session.h>
45 #include <SVTK_Selector.h>
46 #include <SVTK_ViewWindow.h>
47 #include <SALOME_ListIO.hxx>
50 #include <TColStd_MapOfInteger.hxx>
51 #include <TColStd_IndexedMapOfInteger.hxx>
54 #include <QVBoxLayout>
55 #include <QHBoxLayout>
57 #include <QPushButton>
68 \brief Simple 'busy state' flag locker.
75 //! Constructor. Sets passed boolean flag to \c true.
76 BusyLocker( bool& busy ) : myBusy( busy ) { myBusy = true; }
77 //! Destructor. Clear external boolean flag passed as parameter to the constructor to \c false.
78 ~BusyLocker() { myBusy = false; }
80 bool& myBusy; //! External 'busy state' boolean flag
84 * Class : SMESHGUI_SingleEditDlg
85 * Description : Inversion of the diagonal of a pseudo-quadrangle formed by
86 * 2 neighboring triangles with 1 common edge
89 //=======================================================================
90 // name : SMESHGUI_SingleEditDlg()
91 // Purpose : Constructor
92 //=======================================================================
93 SMESHGUI_SingleEditDlg
94 ::SMESHGUI_SingleEditDlg(SMESHGUI* theModule)
95 : QDialog(SMESH::GetDesktop(theModule)),
96 mySelector(SMESH::GetViewWindow(theModule)->GetSelector()),
97 mySelectionMgr(SMESH::GetSelectionMgr(theModule)),
102 QVBoxLayout* aDlgLay = new QVBoxLayout(this);
103 aDlgLay->setMargin(MARGIN);
104 aDlgLay->setSpacing(SPACING);
106 QWidget* aMainFrame = createMainFrame (this);
107 QWidget* aBtnFrame = createButtonFrame(this);
109 aDlgLay->addWidget(aMainFrame);
110 aDlgLay->addWidget(aBtnFrame);
115 //=======================================================================
116 // name : createMainFrame()
117 // Purpose : Create frame containing dialog's input fields
118 //=======================================================================
119 QWidget* SMESHGUI_SingleEditDlg::createMainFrame (QWidget* theParent)
121 QGroupBox* aMainGrp = new QGroupBox(tr("EDGE_BETWEEN"), theParent);
122 QHBoxLayout* aLay = new QHBoxLayout(aMainGrp);
123 aLay->setMargin(MARGIN);
124 aLay->setSpacing(SPACING);
126 QPixmap aPix (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
128 QLabel* aLab = new QLabel(tr("SMESH_EDGE"), aMainGrp);
129 QPushButton* aBtn = new QPushButton(aMainGrp);
131 myEdge = new QLineEdit(aMainGrp);
132 myEdge->setValidator(new QRegExpValidator(QRegExp("[\\d]*-[\\d]*"), this));
134 aLay->addWidget(aLab);
135 aLay->addWidget(aBtn);
136 aLay->addWidget(myEdge);
141 //=======================================================================
142 // name : createButtonFrame()
143 // Purpose : Create frame containing buttons
144 //=======================================================================
145 QWidget* SMESHGUI_SingleEditDlg::createButtonFrame (QWidget* theParent)
147 QGroupBox* aFrame = new QGroupBox(theParent);
149 myOkBtn = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), aFrame);
150 myApplyBtn = new QPushButton(tr("SMESH_BUT_APPLY"), aFrame);
151 myCloseBtn = new QPushButton(tr("SMESH_BUT_CLOSE"), aFrame);
152 myHelpBtn = new QPushButton(tr("SMESH_BUT_HELP"), aFrame);
154 QHBoxLayout* aLay = new QHBoxLayout(aFrame);
155 aLay->setMargin(MARGIN);
156 aLay->setSpacing(SPACING);
158 aLay->addWidget(myOkBtn);
159 aLay->addSpacing(10);
160 aLay->addWidget(myApplyBtn);
161 aLay->addSpacing(10);
163 aLay->addWidget(myCloseBtn);
164 aLay->addWidget(myHelpBtn);
169 //=======================================================================
171 // Purpose : Verify validity of input data
172 //=======================================================================
173 bool SMESHGUI_SingleEditDlg::isValid (const bool theMess) const
176 return getNodeIds(myEdge->text(), id1, id2);
179 //=======================================================================
180 // name : getNodeIds()
181 // Purpose : Retrieve node ids from string
182 //=======================================================================
183 bool SMESHGUI_SingleEditDlg::getNodeIds (const QString& theStr,
184 int& theId1, int& theId2) const
186 if (!theStr.contains('-'))
190 QString str1 = theStr.section('-', 0, 0, QString::SectionSkipEmpty);
191 QString str2 = theStr.section('-', 1, 1, QString::SectionSkipEmpty);
192 theId1 = str1.toInt(&ok1);
193 theId2 = str2.toInt(&ok2);
198 //=======================================================================
199 // name : ~SMESHGUI_SingleEditDlg()
200 // Purpose : Destructor
201 //=======================================================================
202 SMESHGUI_SingleEditDlg::~SMESHGUI_SingleEditDlg()
206 //=======================================================================
208 // Purpose : Init dialog fields, connect signals and slots, show dialog
209 //=======================================================================
210 void SMESHGUI_SingleEditDlg::Init()
212 mySMESHGUI->SetActiveDialogBox((QDialog*)this);
217 connect(myOkBtn, SIGNAL(clicked()), SLOT(onOk()));
218 connect(myCloseBtn, SIGNAL(clicked()), SLOT(reject()));
219 connect(myApplyBtn, SIGNAL(clicked()), SLOT(onApply()));
220 connect(myHelpBtn, SIGNAL(clicked()), SLOT(onHelp()));
222 // selection and SMESHGUI
223 connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
224 connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
225 connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(reject()));
226 connect(myEdge, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
228 myOkBtn->setEnabled(false);
229 myApplyBtn->setEnabled(false);
232 // set selection mode
233 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
234 aViewWindow->SetSelectionMode(EdgeOfCellSelection);
239 //=======================================================================
241 // Purpose : SLOT called when "Ok" button pressed.
242 // Assign filters VTK viewer and close dialog
243 //=======================================================================
244 void SMESHGUI_SingleEditDlg::onOk()
250 //=======================================================================
252 // Purpose : SLOT called when "Close" button pressed. Close dialog
253 //=======================================================================
254 void SMESHGUI_SingleEditDlg::reject()
256 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
257 aViewWindow->SetSelectionMode(ActorSelection);
258 //mySelectionMgr->clearSelected();
259 disconnect(mySelectionMgr, 0, this, 0);
260 disconnect(mySMESHGUI, 0, this, 0);
261 mySMESHGUI->ResetState();
265 //=================================================================================
266 // function : onHelp()
268 //=================================================================================
269 void SMESHGUI_SingleEditDlg::onHelp()
271 LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
273 app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
277 platform = "winapplication";
279 platform = "application";
281 SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
282 tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
283 arg(app->resourceMgr()->stringValue("ExternalBrowser",
285 arg(myHelpFileName));
289 //=======================================================================
290 //function : findTriangles()
291 //purpose : find triangles sharing theNode1-theNode2 link
292 // THIS IS A PIECE OF SMESH_MeshEditor.cxx
293 // TO DO: make it available in SMDS for ex.
294 //=======================================================================
295 static bool findTriangles (const SMDS_MeshNode * theNode1,
296 const SMDS_MeshNode * theNode2,
297 const SMDS_MeshElement*& theTria1,
298 const SMDS_MeshElement*& theTria2)
300 if (!theNode1 || !theNode2) return false;
302 theTria1 = theTria2 = 0;
304 std::set< const SMDS_MeshElement* > emap;
305 SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator();
307 const SMDS_MeshElement* elem = it->next();
308 if (elem->GetType() == SMDSAbs_Face && elem->NbNodes() == 3)
311 it = theNode2->GetInverseElementIterator();
313 const SMDS_MeshElement* elem = it->next();
314 if (elem->GetType() == SMDSAbs_Face &&
315 emap.find(elem) != emap.end())
325 return (theTria1 && theTria2);
328 //=======================================================================
329 //function : onTextChange()
331 //=======================================================================
332 void SMESHGUI_SingleEditDlg::onTextChange (const QString& theNewText)
335 BusyLocker lock(myBusy);
337 myOkBtn->setEnabled(false);
338 myApplyBtn->setEnabled(false);
340 // hilight entered edge
342 if(SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh()){
343 Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
346 mySelectionMgr->setSelectedObjects(aList,false);
348 TColStd_IndexedMapOfInteger selectedIndices;
349 TColStd_MapOfInteger newIndices;
350 mySelector->GetIndex(anIO,selectedIndices);
353 if ( !getNodeIds(myEdge->text(), id1, id2) )
356 const SMDS_MeshNode* aNode1 = aMesh->FindNode( id1 );
357 const SMDS_MeshNode* aNode2 = aMesh->FindNode( id2 );
359 if ( !aNode1 || !aNode2 || aNode1 == aNode2 )
362 // find a triangle and an edge index
363 const SMDS_MeshElement* tria1;
364 const SMDS_MeshElement* tria2;
366 if ( findTriangles(aNode1,aNode2,tria1,tria2) )
368 newIndices.Add(tria1->GetID());
370 const SMDS_MeshNode* a3Nodes[3];
371 SMDS_ElemIteratorPtr it;
373 for (i = 0, it = tria1->nodesIterator(); it->more(); i++) {
374 a3Nodes[ i ] = static_cast<const SMDS_MeshNode*>(it->next());
375 if (i > 0 && ( (a3Nodes[ i ] == aNode1 && a3Nodes[ i - 1] == aNode2) ||
376 (a3Nodes[ i ] == aNode2 && a3Nodes[ i - 1] == aNode1) ) ) {
381 newIndices.Add(-edgeInd-1);
383 myOkBtn->setEnabled(true);
384 myApplyBtn->setEnabled(true);
386 mySelector->AddOrRemoveIndex(anIO,newIndices, false);
387 SMESH::GetViewWindow(mySMESHGUI)->highlight( anIO, true, true );
392 //=======================================================================
393 // name : onSelectionDone()
394 // Purpose : SLOT called when selection changed
395 //=======================================================================
396 void SMESHGUI_SingleEditDlg::onSelectionDone()
399 BusyLocker lock(myBusy);
401 int anId1 = 0, anId2 = 0;
403 myOkBtn->setEnabled(false);
404 myApplyBtn->setEnabled(false);
407 mySelectionMgr->selectedObjects(aList);
409 if (aList.Extent() != 1) {
414 Handle(SALOME_InteractiveObject) anIO = aList.First();
415 myActor = SMESH::FindActorByEntry(anIO->getEntry());
417 TVisualObjPtr aVisualObj = myActor->GetObject();
418 if(SMDS_Mesh* aMesh = aVisualObj->GetMesh())
420 const SMDS_MeshElement* tria[2];
421 if( SMESH::GetEdgeNodes( mySelector, aVisualObj, anId1, anId2 ) >= 1 &&
422 findTriangles( aMesh->FindNode( anId1 ), aMesh->FindNode( anId2 ), tria[0],tria[1] ) )
424 QString aText = QString("%1-%2").arg(anId1).arg(anId2);
425 myEdge->setText(aText);
427 myOkBtn->setEnabled(true);
428 myApplyBtn->setEnabled(true);
438 //=======================================================================
439 // name : onDeactivate()
440 // Purpose : SLOT called when dialog must be deativated
441 //=======================================================================
442 void SMESHGUI_SingleEditDlg::onDeactivate()
447 //=======================================================================
448 // name : enterEvent()
449 // Purpose : Event filter
450 //=======================================================================
451 void SMESHGUI_SingleEditDlg::enterEvent (QEvent*)
454 mySMESHGUI->EmitSignalDeactivateDialog();
455 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
456 aViewWindow->SetSelectionMode(EdgeOfCellSelection);
461 //=================================================================================
462 // function : onApply()
463 // purpose : SLOT. Called when apply button is pressed
464 //=================================================================================
465 bool SMESHGUI_SingleEditDlg::onApply()
467 if (mySMESHGUI->isActiveStudyLocked())
469 // verify validity of input data
473 // get mesh, actor and nodes
475 mySelectionMgr->selectedObjects(aList);
477 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(aList.First());
479 if (aMesh->_is_nil()) {
480 SUIT_MessageBox::information(SMESH::GetDesktop(mySMESHGUI),
482 tr("SMESHG_NO_MESH"));
486 SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
487 int anId1= 0, anId2 = 0;
488 if (aMeshEditor->_is_nil() || !getNodeIds(myEdge->text(), anId1, anId2))
492 bool aResult = process(aMeshEditor.in(), anId1, anId2);
496 mySelector->ClearIndex();
497 mySelectionMgr->setSelectedObjects(aList, false);
500 SMESHGUI::Modified();
506 //=================================================================================
507 // function : keyPressEvent()
509 //=================================================================================
510 void SMESHGUI_SingleEditDlg::keyPressEvent( QKeyEvent* e )
512 QDialog::keyPressEvent( e );
513 if ( e->isAccepted() )
516 if ( e->key() == Qt::Key_F1 ) {
523 * Class : SMESHGUI_TrianglesInversionDlg
524 * Description : Inversion of the diagonal of a pseudo-quadrangle formed by
525 * 2 neighboring triangles with 1 common edge
528 SMESHGUI_TrianglesInversionDlg
529 ::SMESHGUI_TrianglesInversionDlg(SMESHGUI* theModule)
530 : SMESHGUI_SingleEditDlg(theModule)
532 setWindowTitle(tr("CAPTION"));
533 myHelpFileName = "diagonal_inversion_of_elements_page.html";
536 SMESHGUI_TrianglesInversionDlg::~SMESHGUI_TrianglesInversionDlg()
540 bool SMESHGUI_TrianglesInversionDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
541 const int theId1, const int theId2)
543 return theMeshEditor->InverseDiag(theId1, theId2);
547 * Class : SMESHGUI_UnionOfTwoTrianglesDlg
548 * Description : Construction of a quadrangle by deletion of the
549 * common border of 2 neighboring triangles
552 SMESHGUI_UnionOfTwoTrianglesDlg
553 ::SMESHGUI_UnionOfTwoTrianglesDlg(SMESHGUI* theModule)
554 : SMESHGUI_SingleEditDlg(theModule)
556 setWindowTitle(tr("CAPTION"));
557 myHelpFileName = "uniting_two_triangles_page.html";
560 SMESHGUI_UnionOfTwoTrianglesDlg::~SMESHGUI_UnionOfTwoTrianglesDlg()
564 bool SMESHGUI_UnionOfTwoTrianglesDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
565 const int theId1, const int theId2)
567 return theMeshEditor->DeleteDiag(theId1, theId2);