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 "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 * Class : SMESHGUI_DiagValidator
73 * Description : validate munual input of edge like "id1-id2"
75 class SMESHGUI_DiagValidator: public QValidator
78 SMESHGUI_DiagValidator (QWidget * parent, const char * name = 0):
79 QValidator(parent,name) {}
81 State validate (QString & text, int & pos) const
83 text.stripWhiteSpace();
84 text.replace(QRegExp("[^0-9]+"), "-");
87 int ind = text.find(QRegExp("-[0-9]+-"));
88 if (ind > 0) { // leave only two ids
89 ind = text.find('-', ind + 1);
93 if (pos > text.length())
100 * Class : SMESHGUI_SingleEditDlg
101 * Description : Inversion of the diagonal of a pseudo-quadrangle formed by
102 * 2 neighboring triangles with 1 common edge
105 //=======================================================================
106 // name : SMESHGUI_SingleEditDlg()
107 // Purpose : Constructor
108 //=======================================================================
109 SMESHGUI_SingleEditDlg
110 ::SMESHGUI_SingleEditDlg(SMESHGUI* theModule,
111 const char* theName):
112 QDialog(SMESH::GetDesktop(theModule),
115 WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
116 mySelector(SMESH::GetViewWindow(theModule)->GetSelector()),
117 mySelectionMgr(SMESH::GetSelectionMgr(theModule)),
118 mySMESHGUI(theModule)
120 QVBoxLayout* aDlgLay = new QVBoxLayout(this, MARGIN, SPACING);
122 QFrame* aMainFrame = createMainFrame (this);
123 QFrame* aBtnFrame = createButtonFrame(this);
125 aDlgLay->addWidget(aMainFrame);
126 aDlgLay->addWidget(aBtnFrame);
128 aDlgLay->setStretchFactor(aMainFrame, 1);
133 //=======================================================================
134 // name : createMainFrame()
135 // Purpose : Create frame containing dialog's input fields
136 //=======================================================================
137 QFrame* SMESHGUI_SingleEditDlg::createMainFrame (QWidget* theParent)
139 QGroupBox* aMainGrp = new QGroupBox(1, Qt::Vertical, tr("EDGE_BETWEEN"), theParent);
141 QPixmap aPix (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
143 new QLabel(tr("SMESH_EDGE"), aMainGrp);
144 (new QPushButton(aMainGrp))->setPixmap(aPix);
145 myEdge = new QLineEdit(aMainGrp);
146 myEdge->setValidator(new SMESHGUI_DiagValidator(this, "validator"));
151 //=======================================================================
152 // name : createButtonFrame()
153 // Purpose : Create frame containing buttons
154 //=======================================================================
155 QFrame* SMESHGUI_SingleEditDlg::createButtonFrame (QWidget* theParent)
157 QFrame* aFrame = new QFrame(theParent);
158 aFrame->setFrameStyle(QFrame::Box | QFrame::Sunken);
160 myOkBtn = new QPushButton(tr("SMESH_BUT_OK" ), aFrame);
161 myApplyBtn = new QPushButton(tr("SMESH_BUT_APPLY"), aFrame);
162 myCloseBtn = new QPushButton(tr("SMESH_BUT_CLOSE"), aFrame);
163 myHelpBtn = new QPushButton (tr("SMESH_BUT_HELP"), aFrame);
165 QSpacerItem* aSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
167 QHBoxLayout* aLay = new QHBoxLayout(aFrame, MARGIN, SPACING);
169 aLay->addWidget(myOkBtn);
170 aLay->addWidget(myApplyBtn);
171 aLay->addItem(aSpacer);
172 aLay->addWidget(myCloseBtn);
173 aLay->addWidget(myHelpBtn);
178 //=======================================================================
180 // Purpose : Verify validity of input data
181 //=======================================================================
182 bool SMESHGUI_SingleEditDlg::isValid (const bool theMess) const
185 return getNodeIds(myEdge->text(), id1, id2);
188 //=======================================================================
189 // name : getNodeIds()
190 // Purpose : Retrieve node ids from string
191 //=======================================================================
192 bool SMESHGUI_SingleEditDlg::getNodeIds (const QString& theStr,
193 int& theId1, int& theId2) const
195 if (!theStr.contains('-'))
199 QString str1 = theStr.section('-', 0, 0, QString::SectionSkipEmpty);
200 QString str2 = theStr.section('-', 1, 1, QString::SectionSkipEmpty);
201 theId1 = str1.toInt(&ok1);
202 theId2 = str2.toInt(&ok2);
207 //=======================================================================
208 // name : ~SMESHGUI_SingleEditDlg()
209 // Purpose : Destructor
210 //=======================================================================
211 SMESHGUI_SingleEditDlg::~SMESHGUI_SingleEditDlg()
215 //=======================================================================
217 // Purpose : Init dialog fields, connect signals and slots, show dialog
218 //=======================================================================
219 void SMESHGUI_SingleEditDlg::Init()
221 mySMESHGUI->SetActiveDialogBox((QDialog*)this);
226 connect(myOkBtn, SIGNAL(clicked()), SLOT(onOk()));
227 connect(myCloseBtn, SIGNAL(clicked()), SLOT(onClose()));
228 connect(myApplyBtn, SIGNAL(clicked()), SLOT(onApply()));
229 connect(myHelpBtn, SIGNAL(clicked()), SLOT(onHelp()));
231 // selection and SMESHGUI
232 connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
233 connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
234 connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(onClose()));
235 connect(myEdge, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
237 myOkBtn->setEnabled(false);
238 myApplyBtn->setEnabled(false);
243 // set selection mode
244 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
245 aViewWindow->SetSelectionMode(EdgeOfCellSelection);
250 //=======================================================================
252 // Purpose : SLOT called when "Ok" button pressed.
253 // Assign filters VTK viewer and close dialog
254 //=======================================================================
255 void SMESHGUI_SingleEditDlg::onOk()
261 //=======================================================================
263 // Purpose : SLOT called when "Close" button pressed. Close dialog
264 //=======================================================================
265 void SMESHGUI_SingleEditDlg::onClose()
267 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
268 aViewWindow->SetSelectionMode(ActorSelection);
269 //mySelectionMgr->clearSelected();
270 disconnect(mySelectionMgr, 0, this, 0);
271 disconnect(mySMESHGUI, 0, this, 0);
272 mySMESHGUI->ResetState();
276 //=================================================================================
277 // function : onHelp()
279 //=================================================================================
280 void SMESHGUI_SingleEditDlg::onHelp()
282 LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
284 app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
286 SUIT_MessageBox::warn1(0, QObject::tr("WRN_WARNING"),
287 QObject::tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
288 arg(app->resourceMgr()->stringValue("ExternalBrowser", "application")).arg(myHelpFileName),
289 QObject::tr("BUT_OK"));
293 //=======================================================================
294 //function : findTriangles()
295 //purpose : find triangles sharing theNode1-theNode2 link
296 // THIS IS A PIECE OF SMESH_MeshEditor.cxx
297 // TO DO: make it available in SMDS for ex.
298 //=======================================================================
299 static bool findTriangles (const SMDS_MeshNode * theNode1,
300 const SMDS_MeshNode * theNode2,
301 const SMDS_MeshElement*& theTria1,
302 const SMDS_MeshElement*& theTria2)
304 if (!theNode1 || !theNode2) return false;
306 theTria1 = theTria2 = 0;
308 set< const SMDS_MeshElement* > emap;
309 SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator();
311 const SMDS_MeshElement* elem = it->next();
312 if (elem->GetType() == SMDSAbs_Face && elem->NbNodes() == 3)
315 it = theNode2->GetInverseElementIterator();
317 const SMDS_MeshElement* elem = it->next();
318 if (elem->GetType() == SMDSAbs_Face &&
319 emap.find(elem) != emap.end())
327 return (theTria1 && theTria2);
330 //=======================================================================
331 //function : onTextChange()
333 //=======================================================================
334 void SMESHGUI_SingleEditDlg::onTextChange (const QString& theNewText)
338 myOkBtn->setEnabled(false);
339 myApplyBtn->setEnabled(false);
341 // hilight entered edge
343 if(SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh()){
344 myBusy = true; // block onSelectionDone()
345 Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
348 mySelectionMgr->setSelectedObjects(aList,false);
350 TColStd_IndexedMapOfInteger selectedIndices;
351 TColStd_MapOfInteger newIndices;
352 mySelector->GetIndex(anIO,selectedIndices);
355 QStringList aListId = QStringList::split("-", theNewText, false);
356 if (aListId.count() != 2)
361 const SMDS_MeshNode* a2Nodes[2];
362 for (i = 0; i < aListId.count(); i++) {
363 if(const SMDS_MeshNode *aNode = aMesh->FindNode(aListId[ i ].toInt()))
364 a2Nodes[ i ] = aNode;
369 // find a triangle and an edge nb
370 const SMDS_MeshElement* tria[2];
371 allOk &= a2Nodes[0] != a2Nodes[1] && findTriangles(a2Nodes[0],a2Nodes[1],tria[0],tria[1]);
372 myBusy = true; // block onSelectionDone()
375 newIndices.Add(tria[0]->GetID());
377 const SMDS_MeshNode* a3Nodes [3];
378 SMDS_ElemIteratorPtr it;
380 for (i = 0, it = tria[0]->nodesIterator(); it->more(); i++) {
381 a3Nodes[ i ] = static_cast<const SMDS_MeshNode*>(it->next());
383 allOk = (a3Nodes[ i ] == a2Nodes[ 0 ] && a3Nodes[ i - 1] == a2Nodes[ 1 ]) ||
384 (a3Nodes[ i ] == a2Nodes[ 1 ] && a3Nodes[ i - 1] == a2Nodes[ 0 ]);
391 newIndices.Add(-edgeInd-1);
393 myOkBtn->setEnabled(true);
394 myApplyBtn->setEnabled(true);
396 mySelector->AddOrRemoveIndex(anIO,newIndices, false);
397 SMESH::GetViewWindow(mySMESHGUI)->highlight( anIO, true, true );
404 //=======================================================================
405 // name : onSelectionDone()
406 // Purpose : SLOT called when selection changed
407 //=======================================================================
408 void SMESHGUI_SingleEditDlg::onSelectionDone()
412 int anId1 = 0, anId2 = 0;
414 myOkBtn->setEnabled(false);
415 myApplyBtn->setEnabled(false);
418 mySelectionMgr->selectedObjects(aList);
420 if (aList.Extent() != 1) {
425 Handle(SALOME_InteractiveObject) anIO = aList.First();
426 myActor = SMESH::FindActorByEntry(anIO->getEntry());
428 TVisualObjPtr aVisualObj = myActor->GetObject();
429 if(SMDS_Mesh* aMesh = aVisualObj->GetMesh())
431 const SMDS_MeshElement* tria[2];
432 if( SMESH::GetEdgeNodes( mySelector, aVisualObj, anId1, anId2 ) >= 1 &&
433 findTriangles( aMesh->FindNode( anId1 ), aMesh->FindNode( anId2 ), tria[0],tria[1] ) )
435 QString aText = QString("%1-%2").arg(anId1).arg(anId2);
437 myEdge->setText(aText);
440 myOkBtn->setEnabled(true);
441 myApplyBtn->setEnabled(true);
451 //=======================================================================
452 // name : onDeactivate()
453 // Purpose : SLOT called when dialog must be deativated
454 //=======================================================================
455 void SMESHGUI_SingleEditDlg::onDeactivate()
460 //=======================================================================
461 // name : enterEvent()
462 // Purpose : Event filter
463 //=======================================================================
464 void SMESHGUI_SingleEditDlg::enterEvent (QEvent*)
467 mySMESHGUI->EmitSignalDeactivateDialog();
468 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
469 aViewWindow->SetSelectionMode(EdgeOfCellSelection);
474 //=================================================================================
475 // function : closeEvent()
477 //=================================================================================
478 void SMESHGUI_SingleEditDlg::closeEvent (QCloseEvent*)
483 //=======================================================================
484 //function : hideEvent()
485 //purpose : caused by ESC key
486 //=======================================================================
487 void SMESHGUI_SingleEditDlg::hideEvent (QHideEvent*)
493 //=================================================================================
494 // function : onApply()
495 // purpose : SLOT. Called when apply button is pressed
496 //=================================================================================
497 bool SMESHGUI_SingleEditDlg::onApply()
499 if (mySMESHGUI->isActiveStudyLocked())
501 // verify validity of input data
505 // get mesh, actor and nodes
507 mySelectionMgr->selectedObjects(aList);
509 SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(aList.First());
511 if (aMesh->_is_nil()) {
512 SUIT_MessageBox::info1(SMESH::GetDesktop(mySMESHGUI),
514 tr("SMESHG_NO_MESH"),
519 SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
520 int anId1= 0, anId2 = 0;
521 if (aMeshEditor->_is_nil() || !getNodeIds(myEdge->text(), anId1, anId2))
525 bool aResult = process(aMeshEditor.in(), anId1, anId2);
529 mySelector->ClearIndex();
530 mySelectionMgr->setSelectedObjects(aList, false);
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 = "/files/diagonal_iversion_of_elements.htm";
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 = "/files/uniting_two_triangles.htm";
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);