1 // Copyright (C) 2007-2008 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
22 // SMESH SMESHGUI : GUI for SMESH component
23 // File : SMESHGUI_SingleEditDlg.cxx
24 // Author : Sergey LITONIN
27 #include "SMESHGUI_SingleEditDlg.h"
30 #include "SMESHGUI_Utils.h"
31 #include "SMESHGUI_VTKUtils.h"
32 #include "SMESHGUI_MeshUtils.h"
33 #include "SMESHGUI_SpinBox.h"
35 #include "SMESH_Actor.h"
36 #include "SMDS_Mesh.hxx"
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"
49 #include "utilities.h"
52 #include <TColStd_MapOfInteger.hxx>
53 #include <TColStd_IndexedMapOfInteger.hxx>
58 #include <qlineedit.h>
59 #include <qpushbutton.h>
60 #include <qgroupbox.h>
62 #include <qmessagebox.h>
63 #include <qvalidator.h>
73 \brief Simple 'busy state' flag locker.
80 //! Constructor. Sets passed boolean flag to \c true.
81 BusyLocker( bool& busy ) : myBusy( busy ) { myBusy = true; }
82 //! Destructor. Clear external boolean flag passed as parameter to the constructor to \c false.
83 ~BusyLocker() { myBusy = false; }
85 bool& myBusy; //! External 'busy state' boolean flag
89 * Class : SMESHGUI_SingleEditDlg
90 * Description : Inversion of the diagonal of a pseudo-quadrangle formed by
91 * 2 neighboring triangles with 1 common edge
94 //=======================================================================
95 // name : SMESHGUI_SingleEditDlg()
96 // Purpose : Constructor
97 //=======================================================================
98 SMESHGUI_SingleEditDlg
99 ::SMESHGUI_SingleEditDlg(SMESHGUI* theModule,
100 const char* theName):
101 QDialog(SMESH::GetDesktop(theModule),
104 WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
105 mySelector(SMESH::GetViewWindow(theModule)->GetSelector()),
106 mySelectionMgr(SMESH::GetSelectionMgr(theModule)),
107 mySMESHGUI(theModule)
109 QVBoxLayout* aDlgLay = new QVBoxLayout(this, MARGIN, SPACING);
111 QFrame* aMainFrame = createMainFrame (this);
112 QFrame* aBtnFrame = createButtonFrame(this);
114 aDlgLay->addWidget(aMainFrame);
115 aDlgLay->addWidget(aBtnFrame);
117 aDlgLay->setStretchFactor(aMainFrame, 1);
122 //=======================================================================
123 // name : createMainFrame()
124 // Purpose : Create frame containing dialog's input fields
125 //=======================================================================
126 QFrame* SMESHGUI_SingleEditDlg::createMainFrame (QWidget* theParent)
128 QGroupBox* aMainGrp = new QGroupBox(1, Qt::Vertical, tr("EDGE_BETWEEN"), theParent);
130 QPixmap aPix (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
132 new QLabel(tr("SMESH_EDGE"), aMainGrp);
133 (new QPushButton(aMainGrp))->setPixmap(aPix);
134 myEdge = new QLineEdit(aMainGrp);
135 myEdge->setValidator(new QRegExpValidator(QRegExp("[\\d]*-[\\d]*"), this));
140 //=======================================================================
141 // name : createButtonFrame()
142 // Purpose : Create frame containing buttons
143 //=======================================================================
144 QFrame* SMESHGUI_SingleEditDlg::createButtonFrame (QWidget* theParent)
146 QFrame* aFrame = new QFrame(theParent);
147 aFrame->setFrameStyle(QFrame::Box | QFrame::Sunken);
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 QSpacerItem* aSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
156 QHBoxLayout* aLay = new QHBoxLayout(aFrame, MARGIN, SPACING);
158 aLay->addWidget(myOkBtn);
159 aLay->addWidget(myApplyBtn);
160 aLay->addItem(aSpacer);
161 aLay->addWidget(myCloseBtn);
162 aLay->addWidget(myHelpBtn);
167 //=======================================================================
169 // Purpose : Verify validity of input data
170 //=======================================================================
171 bool SMESHGUI_SingleEditDlg::isValid (const bool theMess) const
174 return getNodeIds(myEdge->text(), id1, id2);
177 //=======================================================================
178 // name : getNodeIds()
179 // Purpose : Retrieve node ids from string
180 //=======================================================================
181 bool SMESHGUI_SingleEditDlg::getNodeIds (const QString& theStr,
182 int& theId1, int& theId2) const
184 if (!theStr.contains('-'))
188 QString str1 = theStr.section('-', 0, 0, QString::SectionSkipEmpty);
189 QString str2 = theStr.section('-', 1, 1, QString::SectionSkipEmpty);
190 theId1 = str1.toInt(&ok1);
191 theId2 = str2.toInt(&ok2);
196 //=======================================================================
197 // name : ~SMESHGUI_SingleEditDlg()
198 // Purpose : Destructor
199 //=======================================================================
200 SMESHGUI_SingleEditDlg::~SMESHGUI_SingleEditDlg()
204 //=======================================================================
206 // Purpose : Init dialog fields, connect signals and slots, show dialog
207 //=======================================================================
208 void SMESHGUI_SingleEditDlg::Init()
210 mySMESHGUI->SetActiveDialogBox((QDialog*)this);
215 connect(myOkBtn, SIGNAL(clicked()), SLOT(onOk()));
216 connect(myCloseBtn, SIGNAL(clicked()), SLOT(onClose()));
217 connect(myApplyBtn, SIGNAL(clicked()), SLOT(onApply()));
218 connect(myHelpBtn, SIGNAL(clicked()), SLOT(onHelp()));
220 // selection and SMESHGUI
221 connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
222 connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
223 connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(onClose()));
224 connect(myEdge, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
226 myOkBtn->setEnabled(false);
227 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::onClose()
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::warn1(0, QObject::tr("WRN_WARNING"),
282 QObject::tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
283 arg(app->resourceMgr()->stringValue("ExternalBrowser", platform)).arg(myHelpFileName),
284 QObject::tr("BUT_OK"));
288 //=======================================================================
289 //function : findTriangles()
290 //purpose : find triangles sharing theNode1-theNode2 link
291 // THIS IS A PIECE OF SMESH_MeshEditor.cxx
292 // TO DO: make it available in SMDS for ex.
293 //=======================================================================
294 static bool findTriangles (const SMDS_MeshNode * theNode1,
295 const SMDS_MeshNode * theNode2,
296 const SMDS_MeshElement*& theTria1,
297 const SMDS_MeshElement*& theTria2)
299 if (!theNode1 || !theNode2) return false;
301 theTria1 = theTria2 = 0;
303 set< const SMDS_MeshElement* > emap;
304 SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator();
306 const SMDS_MeshElement* elem = it->next();
307 if (elem->GetType() == SMDSAbs_Face && elem->NbNodes() == 3)
310 it = theNode2->GetInverseElementIterator();
312 const SMDS_MeshElement* elem = it->next();
313 if (elem->GetType() == SMDSAbs_Face &&
314 emap.find(elem) != emap.end())
322 return (theTria1 && theTria2);
325 //=======================================================================
326 //function : onTextChange()
328 //=======================================================================
329 void SMESHGUI_SingleEditDlg::onTextChange (const QString& theNewText)
332 BusyLocker lock(myBusy);
334 myOkBtn->setEnabled(false);
335 myApplyBtn->setEnabled(false);
337 // hilight entered edge
339 if(SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh()){
340 Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
343 mySelectionMgr->setSelectedObjects(aList,false);
345 TColStd_IndexedMapOfInteger selectedIndices;
346 TColStd_MapOfInteger newIndices;
347 mySelector->GetIndex(anIO,selectedIndices);
350 if ( !getNodeIds(myEdge->text(), id1, id2) )
353 const SMDS_MeshNode* aNode1 = aMesh->FindNode( id1 );
354 const SMDS_MeshNode* aNode2 = aMesh->FindNode( id2 );
356 if ( !aNode1 || !aNode2 || aNode1 == aNode2 )
359 // find a triangle and an edge index
360 const SMDS_MeshElement* tria1;
361 const SMDS_MeshElement* tria2;
363 if ( findTriangles(aNode1,aNode2,tria1,tria2) )
365 newIndices.Add(tria1->GetID());
367 const SMDS_MeshNode* a3Nodes[3];
368 SMDS_ElemIteratorPtr it;
370 for (i = 0, it = tria1->nodesIterator(); it->more(); i++) {
371 a3Nodes[ i ] = static_cast<const SMDS_MeshNode*>(it->next());
372 if (i > 0 && ( a3Nodes[ i ] == aNode1 && a3Nodes[ i - 1] == aNode2 ||
373 a3Nodes[ i ] == aNode2 && a3Nodes[ i - 1] == aNode1 ) ) {
378 newIndices.Add(-edgeInd-1);
380 myOkBtn->setEnabled(true);
381 myApplyBtn->setEnabled(true);
383 mySelector->AddOrRemoveIndex(anIO,newIndices, false);
384 SMESH::GetViewWindow(mySMESHGUI)->highlight( anIO, true, true );
389 //=======================================================================
390 // name : onSelectionDone()
391 // Purpose : SLOT called when selection changed
392 //=======================================================================
393 void SMESHGUI_SingleEditDlg::onSelectionDone()
396 BusyLocker lock(myBusy);
398 int anId1 = 0, anId2 = 0;
400 myOkBtn->setEnabled(false);
401 myApplyBtn->setEnabled(false);
404 mySelectionMgr->selectedObjects(aList);
406 if (aList.Extent() != 1) {
411 Handle(SALOME_InteractiveObject) anIO = aList.First();
412 myActor = SMESH::FindActorByEntry(anIO->getEntry());
414 TVisualObjPtr aVisualObj = myActor->GetObject();
415 if(SMDS_Mesh* aMesh = aVisualObj->GetMesh())
417 const SMDS_MeshElement* tria[2];
418 if( SMESH::GetEdgeNodes( mySelector, aVisualObj, anId1, anId2 ) >= 1 &&
419 findTriangles( aMesh->FindNode( anId1 ), aMesh->FindNode( anId2 ), tria[0],tria[1] ) )
421 QString aText = QString("%1-%2").arg(anId1).arg(anId2);
422 myEdge->setText(aText);
424 myOkBtn->setEnabled(true);
425 myApplyBtn->setEnabled(true);
435 //=======================================================================
436 // name : onDeactivate()
437 // Purpose : SLOT called when dialog must be deativated
438 //=======================================================================
439 void SMESHGUI_SingleEditDlg::onDeactivate()
444 //=======================================================================
445 // name : enterEvent()
446 // Purpose : Event filter
447 //=======================================================================
448 void SMESHGUI_SingleEditDlg::enterEvent (QEvent*)
451 mySMESHGUI->EmitSignalDeactivateDialog();
452 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
453 aViewWindow->SetSelectionMode(EdgeOfCellSelection);
458 //=================================================================================
459 // function : closeEvent()
461 //=================================================================================
462 void SMESHGUI_SingleEditDlg::closeEvent (QCloseEvent*)
467 //=======================================================================
468 //function : hideEvent()
469 //purpose : caused by ESC key
470 //=======================================================================
471 void SMESHGUI_SingleEditDlg::hideEvent (QHideEvent*)
477 //=================================================================================
478 // function : onApply()
479 // purpose : SLOT. Called when apply button is pressed
480 //=================================================================================
481 bool SMESHGUI_SingleEditDlg::onApply()
483 if (mySMESHGUI->isActiveStudyLocked())
485 // verify validity of input data
489 // get mesh, actor and nodes
491 mySelectionMgr->selectedObjects(aList);
493 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(aList.First());
495 if (aMesh->_is_nil()) {
496 SUIT_MessageBox::info1(SMESH::GetDesktop(mySMESHGUI),
498 tr("SMESHG_NO_MESH"),
503 SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
504 int anId1= 0, anId2 = 0;
505 if (aMeshEditor->_is_nil() || !getNodeIds(myEdge->text(), anId1, anId2))
509 bool aResult = process(aMeshEditor.in(), anId1, anId2);
513 mySelector->ClearIndex();
514 mySelectionMgr->setSelectedObjects(aList, false);
522 //=================================================================================
523 // function : keyPressEvent()
525 //=================================================================================
526 void SMESHGUI_SingleEditDlg::keyPressEvent( QKeyEvent* e )
528 QDialog::keyPressEvent( e );
529 if ( e->isAccepted() )
532 if ( e->key() == Key_F1 )
540 * Class : SMESHGUI_TrianglesInversionDlg
541 * Description : Inversion of the diagonal of a pseudo-quadrangle formed by
542 * 2 neighboring triangles with 1 common edge
545 SMESHGUI_TrianglesInversionDlg
546 ::SMESHGUI_TrianglesInversionDlg(SMESHGUI* theModule,
548 : SMESHGUI_SingleEditDlg(theModule,theName)
550 setCaption(tr("CAPTION"));
551 myHelpFileName = "diagonal_inversion_of_elements_page.html";
554 SMESHGUI_TrianglesInversionDlg::~SMESHGUI_TrianglesInversionDlg()
558 bool SMESHGUI_TrianglesInversionDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
559 const int theId1, const int theId2)
561 return theMeshEditor->InverseDiag(theId1, theId2);
565 * Class : SMESHGUI_UnionOfTwoTrianglesDlg
566 * Description : Construction of a quadrangle by deletion of the
567 * common border of 2 neighboring triangles
570 SMESHGUI_UnionOfTwoTrianglesDlg
571 ::SMESHGUI_UnionOfTwoTrianglesDlg(SMESHGUI* theModule,
573 : SMESHGUI_SingleEditDlg(theModule,theName)
575 setCaption(tr("CAPTION"));
576 myHelpFileName = "uniting_two_triangles_page.html";
579 SMESHGUI_UnionOfTwoTrianglesDlg::~SMESHGUI_UnionOfTwoTrianglesDlg()
583 bool SMESHGUI_UnionOfTwoTrianglesDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
584 const int theId1, const int theId2)
586 return theMeshEditor->DeleteDiag(theId1, theId2);