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.salome-platform.org/ or email : webmaster.salome@opencascade.com
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 "LightApp_Application.h"
41 #include "SUIT_ResourceMgr.h"
42 #include "SUIT_MessageBox.h"
43 #include "SUIT_Desktop.h"
44 #include "SUIT_Session.h"
46 #include "SVTK_Selector.h"
47 #include "SVTK_ViewWindow.h"
48 #include "SALOME_ListIO.hxx"
50 #include "utilities.h"
53 #include <TColStd_MapOfInteger.hxx>
54 #include <TColStd_IndexedMapOfInteger.hxx>
59 #include <qlineedit.h>
60 #include <qpushbutton.h>
61 #include <qgroupbox.h>
63 #include <qmessagebox.h>
64 #include <qvalidator.h>
72 \brief Simple 'busy state' flag locker.
79 //! Constructor. Sets passed boolean flag to \c true.
80 BusyLocker( bool& busy ) : myBusy( busy ) { myBusy = true; }
81 //! Destructor. Clear external boolean flag passed as parameter to the constructor to \c false.
82 ~BusyLocker() { myBusy = false; }
84 bool& myBusy; //! External 'busy state' boolean flag
88 * Class : SMESHGUI_SingleEditDlg
89 * Description : Inversion of the diagonal of a pseudo-quadrangle formed by
90 * 2 neighboring triangles with 1 common edge
93 //=======================================================================
94 // name : SMESHGUI_SingleEditDlg()
95 // Purpose : Constructor
96 //=======================================================================
97 SMESHGUI_SingleEditDlg
98 ::SMESHGUI_SingleEditDlg(SMESHGUI* theModule,
100 QDialog(SMESH::GetDesktop(theModule),
103 WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
104 mySelector(SMESH::GetViewWindow(theModule)->GetSelector()),
105 mySelectionMgr(SMESH::GetSelectionMgr(theModule)),
106 mySMESHGUI(theModule)
108 QVBoxLayout* aDlgLay = new QVBoxLayout(this, MARGIN, SPACING);
110 QFrame* aMainFrame = createMainFrame (this);
111 QFrame* aBtnFrame = createButtonFrame(this);
113 aDlgLay->addWidget(aMainFrame);
114 aDlgLay->addWidget(aBtnFrame);
116 aDlgLay->setStretchFactor(aMainFrame, 1);
121 //=======================================================================
122 // name : createMainFrame()
123 // Purpose : Create frame containing dialog's input fields
124 //=======================================================================
125 QFrame* SMESHGUI_SingleEditDlg::createMainFrame (QWidget* theParent)
127 QGroupBox* aMainGrp = new QGroupBox(1, Qt::Vertical, tr("EDGE_BETWEEN"), theParent);
129 QPixmap aPix (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
131 new QLabel(tr("SMESH_EDGE"), aMainGrp);
132 (new QPushButton(aMainGrp))->setPixmap(aPix);
133 myEdge = new QLineEdit(aMainGrp);
134 myEdge->setValidator(new QRegExpValidator(QRegExp("[\\d]*-[\\d]*"), this));
139 //=======================================================================
140 // name : createButtonFrame()
141 // Purpose : Create frame containing buttons
142 //=======================================================================
143 QFrame* SMESHGUI_SingleEditDlg::createButtonFrame (QWidget* theParent)
145 QFrame* aFrame = new QFrame(theParent);
146 aFrame->setFrameStyle(QFrame::Box | QFrame::Sunken);
148 myOkBtn = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE" ), aFrame);
149 myApplyBtn = new QPushButton(tr("SMESH_BUT_APPLY"), aFrame);
150 myCloseBtn = new QPushButton(tr("SMESH_BUT_CLOSE"), aFrame);
151 myHelpBtn = new QPushButton (tr("SMESH_BUT_HELP"), aFrame);
153 QSpacerItem* aSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
155 QHBoxLayout* aLay = new QHBoxLayout(aFrame, MARGIN, SPACING);
157 aLay->addWidget(myOkBtn);
158 aLay->addWidget(myApplyBtn);
159 aLay->addItem(aSpacer);
160 aLay->addWidget(myCloseBtn);
161 aLay->addWidget(myHelpBtn);
166 //=======================================================================
168 // Purpose : Verify validity of input data
169 //=======================================================================
170 bool SMESHGUI_SingleEditDlg::isValid (const bool theMess) const
173 return getNodeIds(myEdge->text(), id1, id2);
176 //=======================================================================
177 // name : getNodeIds()
178 // Purpose : Retrieve node ids from string
179 //=======================================================================
180 bool SMESHGUI_SingleEditDlg::getNodeIds (const QString& theStr,
181 int& theId1, int& theId2) const
183 if (!theStr.contains('-'))
187 QString str1 = theStr.section('-', 0, 0, QString::SectionSkipEmpty);
188 QString str2 = theStr.section('-', 1, 1, QString::SectionSkipEmpty);
189 theId1 = str1.toInt(&ok1);
190 theId2 = str2.toInt(&ok2);
195 //=======================================================================
196 // name : ~SMESHGUI_SingleEditDlg()
197 // Purpose : Destructor
198 //=======================================================================
199 SMESHGUI_SingleEditDlg::~SMESHGUI_SingleEditDlg()
203 //=======================================================================
205 // Purpose : Init dialog fields, connect signals and slots, show dialog
206 //=======================================================================
207 void SMESHGUI_SingleEditDlg::Init()
209 mySMESHGUI->SetActiveDialogBox((QDialog*)this);
214 connect(myOkBtn, SIGNAL(clicked()), SLOT(onOk()));
215 connect(myCloseBtn, SIGNAL(clicked()), SLOT(onClose()));
216 connect(myApplyBtn, SIGNAL(clicked()), SLOT(onApply()));
217 connect(myHelpBtn, SIGNAL(clicked()), SLOT(onHelp()));
219 // selection and SMESHGUI
220 connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
221 connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
222 connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(onClose()));
223 connect(myEdge, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
225 myOkBtn->setEnabled(false);
226 myApplyBtn->setEnabled(false);
231 // set selection mode
232 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
233 aViewWindow->SetSelectionMode(EdgeOfCellSelection);
238 //=======================================================================
240 // Purpose : SLOT called when "Ok" button pressed.
241 // Assign filters VTK viewer and close dialog
242 //=======================================================================
243 void SMESHGUI_SingleEditDlg::onOk()
249 //=======================================================================
251 // Purpose : SLOT called when "Close" button pressed. Close dialog
252 //=======================================================================
253 void SMESHGUI_SingleEditDlg::onClose()
255 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
256 aViewWindow->SetSelectionMode(ActorSelection);
257 //mySelectionMgr->clearSelected();
258 disconnect(mySelectionMgr, 0, this, 0);
259 disconnect(mySMESHGUI, 0, this, 0);
260 mySMESHGUI->ResetState();
264 //=================================================================================
265 // function : onHelp()
267 //=================================================================================
268 void SMESHGUI_SingleEditDlg::onHelp()
270 LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
272 app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
276 platform = "winapplication";
278 platform = "application";
280 SUIT_MessageBox::warn1(0, QObject::tr("WRN_WARNING"),
281 QObject::tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
282 arg(app->resourceMgr()->stringValue("ExternalBrowser", platform)).arg(myHelpFileName),
283 QObject::tr("BUT_OK"));
287 //=======================================================================
288 //function : findTriangles()
289 //purpose : find triangles sharing theNode1-theNode2 link
290 // THIS IS A PIECE OF SMESH_MeshEditor.cxx
291 // TO DO: make it available in SMDS for ex.
292 //=======================================================================
293 static bool findTriangles (const SMDS_MeshNode * theNode1,
294 const SMDS_MeshNode * theNode2,
295 const SMDS_MeshElement*& theTria1,
296 const SMDS_MeshElement*& theTria2)
298 if (!theNode1 || !theNode2) return false;
300 theTria1 = theTria2 = 0;
302 set< const SMDS_MeshElement* > emap;
303 SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator();
305 const SMDS_MeshElement* elem = it->next();
306 if (elem->GetType() == SMDSAbs_Face && elem->NbNodes() == 3)
309 it = theNode2->GetInverseElementIterator();
311 const SMDS_MeshElement* elem = it->next();
312 if (elem->GetType() == SMDSAbs_Face &&
313 emap.find(elem) != emap.end())
321 return (theTria1 && theTria2);
324 //=======================================================================
325 //function : onTextChange()
327 //=======================================================================
328 void SMESHGUI_SingleEditDlg::onTextChange (const QString& theNewText)
331 BusyLocker lock(myBusy);
333 myOkBtn->setEnabled(false);
334 myApplyBtn->setEnabled(false);
336 // hilight entered edge
338 if(SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh()){
339 Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
342 mySelectionMgr->setSelectedObjects(aList,false);
344 TColStd_IndexedMapOfInteger selectedIndices;
345 TColStd_MapOfInteger newIndices;
346 mySelector->GetIndex(anIO,selectedIndices);
349 if ( !getNodeIds(myEdge->text(), id1, id2) )
352 const SMDS_MeshNode* aNode1 = aMesh->FindNode( id1 );
353 const SMDS_MeshNode* aNode2 = aMesh->FindNode( id2 );
355 if ( !aNode1 || !aNode2 || aNode1 == aNode2 )
358 // find a triangle and an edge index
359 const SMDS_MeshElement* tria1;
360 const SMDS_MeshElement* tria2;
362 if ( findTriangles(aNode1,aNode2,tria1,tria2) )
364 newIndices.Add(tria1->GetID());
366 const SMDS_MeshNode* a3Nodes[3];
367 SMDS_ElemIteratorPtr it;
369 for (i = 0, it = tria1->nodesIterator(); it->more(); i++) {
370 a3Nodes[ i ] = static_cast<const SMDS_MeshNode*>(it->next());
371 if (i > 0 && ( a3Nodes[ i ] == aNode1 && a3Nodes[ i - 1] == aNode2 ||
372 a3Nodes[ i ] == aNode2 && a3Nodes[ i - 1] == aNode1 ) ) {
377 newIndices.Add(-edgeInd-1);
379 myOkBtn->setEnabled(true);
380 myApplyBtn->setEnabled(true);
382 mySelector->AddOrRemoveIndex(anIO,newIndices, false);
383 SMESH::GetViewWindow(mySMESHGUI)->highlight( anIO, true, true );
388 //=======================================================================
389 // name : onSelectionDone()
390 // Purpose : SLOT called when selection changed
391 //=======================================================================
392 void SMESHGUI_SingleEditDlg::onSelectionDone()
395 BusyLocker lock(myBusy);
397 int anId1 = 0, anId2 = 0;
399 myOkBtn->setEnabled(false);
400 myApplyBtn->setEnabled(false);
403 mySelectionMgr->selectedObjects(aList);
405 if (aList.Extent() != 1) {
410 Handle(SALOME_InteractiveObject) anIO = aList.First();
411 myActor = SMESH::FindActorByEntry(anIO->getEntry());
413 TVisualObjPtr aVisualObj = myActor->GetObject();
414 if(SMDS_Mesh* aMesh = aVisualObj->GetMesh())
416 const SMDS_MeshElement* tria[2];
417 if( SMESH::GetEdgeNodes( mySelector, aVisualObj, anId1, anId2 ) >= 1 &&
418 findTriangles( aMesh->FindNode( anId1 ), aMesh->FindNode( anId2 ), tria[0],tria[1] ) )
420 QString aText = QString("%1-%2").arg(anId1).arg(anId2);
421 myEdge->setText(aText);
423 myOkBtn->setEnabled(true);
424 myApplyBtn->setEnabled(true);
434 //=======================================================================
435 // name : onDeactivate()
436 // Purpose : SLOT called when dialog must be deativated
437 //=======================================================================
438 void SMESHGUI_SingleEditDlg::onDeactivate()
443 //=======================================================================
444 // name : enterEvent()
445 // Purpose : Event filter
446 //=======================================================================
447 void SMESHGUI_SingleEditDlg::enterEvent (QEvent*)
450 mySMESHGUI->EmitSignalDeactivateDialog();
451 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
452 aViewWindow->SetSelectionMode(EdgeOfCellSelection);
457 //=================================================================================
458 // function : closeEvent()
460 //=================================================================================
461 void SMESHGUI_SingleEditDlg::closeEvent (QCloseEvent*)
466 //=======================================================================
467 //function : hideEvent()
468 //purpose : caused by ESC key
469 //=======================================================================
470 void SMESHGUI_SingleEditDlg::hideEvent (QHideEvent*)
476 //=================================================================================
477 // function : onApply()
478 // purpose : SLOT. Called when apply button is pressed
479 //=================================================================================
480 bool SMESHGUI_SingleEditDlg::onApply()
482 if (mySMESHGUI->isActiveStudyLocked())
484 // verify validity of input data
488 // get mesh, actor and nodes
490 mySelectionMgr->selectedObjects(aList);
492 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(aList.First());
494 if (aMesh->_is_nil()) {
495 SUIT_MessageBox::info1(SMESH::GetDesktop(mySMESHGUI),
497 tr("SMESHG_NO_MESH"),
502 SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
503 int anId1= 0, anId2 = 0;
504 if (aMeshEditor->_is_nil() || !getNodeIds(myEdge->text(), anId1, anId2))
508 bool aResult = process(aMeshEditor.in(), anId1, anId2);
512 mySelector->ClearIndex();
513 mySelectionMgr->setSelectedObjects(aList, false);
521 //=================================================================================
522 // function : keyPressEvent()
524 //=================================================================================
525 void SMESHGUI_SingleEditDlg::keyPressEvent( QKeyEvent* e )
527 QDialog::keyPressEvent( e );
528 if ( e->isAccepted() )
531 if ( e->key() == Key_F1 )
539 * Class : SMESHGUI_TrianglesInversionDlg
540 * Description : Inversion of the diagonal of a pseudo-quadrangle formed by
541 * 2 neighboring triangles with 1 common edge
544 SMESHGUI_TrianglesInversionDlg
545 ::SMESHGUI_TrianglesInversionDlg(SMESHGUI* theModule,
547 : SMESHGUI_SingleEditDlg(theModule,theName)
549 setCaption(tr("CAPTION"));
550 myHelpFileName = "diagonal_inversion_of_elements_page.html";
553 SMESHGUI_TrianglesInversionDlg::~SMESHGUI_TrianglesInversionDlg()
557 bool SMESHGUI_TrianglesInversionDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
558 const int theId1, const int theId2)
560 return theMeshEditor->InverseDiag(theId1, theId2);
564 * Class : SMESHGUI_UnionOfTwoTrianglesDlg
565 * Description : Construction of a quadrangle by deletion of the
566 * common border of 2 neighboring triangles
569 SMESHGUI_UnionOfTwoTrianglesDlg
570 ::SMESHGUI_UnionOfTwoTrianglesDlg(SMESHGUI* theModule,
572 : SMESHGUI_SingleEditDlg(theModule,theName)
574 setCaption(tr("CAPTION"));
575 myHelpFileName = "uniting_two_triangles_page.html";
578 SMESHGUI_UnionOfTwoTrianglesDlg::~SMESHGUI_UnionOfTwoTrianglesDlg()
582 bool SMESHGUI_UnionOfTwoTrianglesDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
583 const int theId1, const int theId2)
585 return theMeshEditor->DeleteDiag(theId1, theId2);