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_CreatePatternDlg.cxx
25 // Author : Sergey LITONIN
28 #include "SMESHGUI_CreatePatternDlg.h"
31 #include "SMESHGUI_SpinBox.h"
32 #include "SMESHGUI_PatternWidget.h"
33 #include "SMESHGUI_Utils.h"
34 #include "SMESHGUI_VTKUtils.h"
35 #include "SMESHGUI_PatternUtils.h"
36 #include "SMESHGUI_GEOMGenUtils.h"
38 #include "SMESH_NumberFilter.hxx"
40 #include "SUIT_ResourceMgr.h"
41 #include "SUIT_Desktop.h"
42 #include "SUIT_FileDlg.h"
44 #include "SalomeApp_Study.h"
45 #include "SalomeApp_DataOwner.h"
46 #include "SalomeApp_SelectionMgr.h"
47 #include "SalomeApp_Tools.h"
49 #include "SALOMEDS_SObject.hxx"
51 #include "SALOME_ListIO.hxx"
52 #include "SVTK_ViewModel.h"
53 #include "SVTK_ViewWindow.h"
54 #include "SVTK_Selector.h"
55 #include "SVTK_Selection.h"
58 #include <TColStd_MapOfInteger.hxx>
63 #include <qlineedit.h>
64 #include <qpushbutton.h>
65 #include <qgroupbox.h>
67 #include <qradiobutton.h>
68 #include <qcheckbox.h>
69 #include <qbuttongroup.h>
70 #include <qmessagebox.h>
71 #include <qapplication.h>
77 * Class : SMESHGUI_CreatePatternDlg
78 * Description : Dialog to specify filters for VTK viewer
81 //=======================================================================
82 // function : SMESHGUI_CreatePatternDlg()
83 // purpose : Constructor
84 //=======================================================================
85 SMESHGUI_CreatePatternDlg::SMESHGUI_CreatePatternDlg( SMESHGUI* theModule,
88 : QDialog( SMESH::GetDesktop( theModule ), theName, false,
89 WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
90 mySMESHGUI( theModule ),
91 mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ),
92 myViewWindow( SMESH::GetViewWindow( theModule ) ),
93 mySelector( myViewWindow->GetSelector() )
95 setCaption(tr("CAPTION"));
97 QVBoxLayout* aDlgLay = new QVBoxLayout (this, MARGIN, SPACING);
99 QFrame* aMainFrame = createMainFrame (this);
100 QFrame* aBtnFrame = createButtonFrame(this);
102 aDlgLay->addWidget(aMainFrame);
103 aDlgLay->addWidget(aBtnFrame);
105 aDlgLay->setStretchFactor(aMainFrame, 1);
110 //=======================================================================
111 // function : createMainFrame()
112 // purpose : Create frame containing dialog's input fields
113 //=======================================================================
114 QFrame* SMESHGUI_CreatePatternDlg::createMainFrame (QWidget* theParent)
116 QPixmap iconSlct (SMESHGUI::resourceMgr()->loadPixmap("SMESH", tr("ICON_SELECT")));
117 QPixmap icon2d (SMESHGUI::resourceMgr()->loadPixmap("SMESH", tr("ICON_PATTERN_2d")));
118 QPixmap icon3d (SMESHGUI::resourceMgr()->loadPixmap("SMESH", tr("ICON_PATTERN_3d")));
119 QPixmap iconSample2d (SMESHGUI::resourceMgr()->loadPixmap("SMESH", tr("ICON_PATTERN_SAMPLE_2D")));
121 QGroupBox* aMainGrp = new QGroupBox(1, Qt::Horizontal, theParent);
122 aMainGrp->setFrameStyle(QFrame::NoFrame);
123 aMainGrp->setInsideMargin(0);
125 // Pattern type group
127 myTypeGrp = new QButtonGroup (1, Qt::Vertical, tr("PATTERN_TYPE"), aMainGrp);
128 mySwitch2d = new QRadioButton (myTypeGrp);
129 mySwitch3d = new QRadioButton (myTypeGrp);
130 mySwitch2d->setPixmap(icon2d);
131 mySwitch3d->setPixmap(icon3d);
132 myTypeGrp->insert(mySwitch2d, Type_2d);
133 myTypeGrp->insert(mySwitch3d, Type_3d);
135 QGroupBox* aPatternGrp = new QGroupBox(1, Qt::Horizontal, tr("PATTERN"), aMainGrp);
137 // Mesh and pattern name group
139 QGroupBox* aMeshGrp = new QGroupBox(1, Qt::Vertical, aPatternGrp);
140 aMeshGrp->setFrameStyle(QFrame::NoFrame);
141 aMeshGrp->setInsideMargin(0);
143 new QLabel(tr("MESH_OR_SUBMESH"), aMeshGrp);
145 QPushButton* aSelBtn = new QPushButton(aMeshGrp);
146 aSelBtn->setPixmap(iconSlct);
147 myMeshEdit = new QLineEdit(aMeshGrp);
148 myMeshEdit->setReadOnly(true);
150 QGroupBox* aPattGrp = new QGroupBox(1, Qt::Vertical, aPatternGrp);
151 aPattGrp->setFrameStyle(QFrame::NoFrame);
152 aPattGrp->setInsideMargin(0);
154 new QLabel(tr("PATTERN_NAME"), aPattGrp);
155 myName = new QLineEdit(aPattGrp);
159 myPicture2d = new SMESHGUI_PatternWidget(aPatternGrp),
160 myPicture2d->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
164 myProjectChk = new QCheckBox(tr("PROJECT"), aPatternGrp);
166 // Connect signals and slots
168 connect(myTypeGrp, SIGNAL(clicked(int) ), SLOT(onTypeChanged(int)));
169 connect(myProjectChk, SIGNAL(toggled(bool)), SLOT(onProject(bool) ));
170 connect(aSelBtn, SIGNAL(clicked() ), SLOT(onSelBtnClicked()));
175 //=======================================================================
176 // function : createButtonFrame()
177 // purpose : Create frame containing buttons
178 //=======================================================================
179 QFrame* SMESHGUI_CreatePatternDlg::createButtonFrame (QWidget* theParent)
181 QFrame* aFrame = new QFrame(theParent);
182 aFrame->setFrameStyle(QFrame::Box | QFrame::Sunken);
184 myOkBtn = new QPushButton(tr("SMESH_BUT_OK" ), aFrame);
185 mySaveBtn = new QPushButton(tr("SAVE" ), aFrame);
186 myCloseBtn = new QPushButton(tr("SMESH_BUT_CANCEL"), aFrame);
188 QSpacerItem* aSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
190 QHBoxLayout* aLay = new QHBoxLayout(aFrame, MARGIN, SPACING);
192 aLay->addWidget(myOkBtn);
193 aLay->addWidget(mySaveBtn);
194 aLay->addItem(aSpacer);
195 aLay->addWidget(myCloseBtn);
197 connect(myOkBtn, SIGNAL(clicked()), SLOT(onOk()));
198 connect(myCloseBtn, SIGNAL(clicked()), SLOT(onClose()));
199 connect(mySaveBtn, SIGNAL(clicked()), SLOT(onSave()));
204 //=======================================================================
205 // function : ~SMESHGUI_CreatePatternDlg()
206 // purpose : Destructor
207 //=======================================================================
208 SMESHGUI_CreatePatternDlg::~SMESHGUI_CreatePatternDlg()
210 // no need to delete child widgets, Qt does it all for us
213 //=======================================================================
214 // function : onProject()
215 // purpose : SLOT. Called when state of "Project nodes on ther face"
216 // checkbox is changed
217 //=======================================================================
218 void SMESHGUI_CreatePatternDlg::onProject (bool)
220 loadFromObject(false);
224 //=======================================================================
226 // purpose : Init dialog fields, connect signals and slots, show dialog
227 //=======================================================================
228 void SMESHGUI_CreatePatternDlg::Init( const int theType )
233 mySubMesh = SMESH::SMESH_subMesh::_nil();
234 myMesh = SMESH::SMESH_Mesh::_nil();
235 myGeomObj = GEOM::GEOM_Object::_nil();
236 myPattern = SMESH::SMESH_Pattern::_nil();
240 mySMESHGUI->SetActiveDialogBox((QDialog*)this);
242 // selection and SMESHGUI
243 connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
244 connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
245 connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(onClose()));
247 mySwitch2d->setEnabled(theType == Type_2d);
248 mySwitch3d->setEnabled(theType == Type_3d);
250 if (theType == Type_2d)
251 myProjectChk->show();
253 myProjectChk->hide();
255 myTypeGrp->setButton(theType);
256 onTypeChanged(theType);
258 myName->setText(getDefaultName());
259 myMeshEdit->setText("");
261 setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));
262 qApp->processEvents();
264 myPicture2d->updateGeometry();
266 resize(minimumSize());
272 mySMESHGUI->DefineDlgPosition(this, x, y);
277 //=======================================================================
278 // function : SetMesh()
279 // purpose : Set mesh to dialog
280 //=======================================================================
281 void SMESHGUI_CreatePatternDlg::SetMesh (SMESH::SMESH_Mesh_ptr thePtr)
283 myMesh = SMESH::SMESH_Mesh::_duplicate(thePtr);
284 mySubMesh = SMESH::SMESH_subMesh::_nil();
286 bool isValidMesh = false;
287 if (!myMesh->_is_nil())
289 _PTR(SObject) aSobj = SMESH::FindSObject(myMesh.in());
290 //Handle(SALOME_InteractiveObject) anIObj =
291 // new SALOME_InteractiveObject(aSobj->GetID().c_str(), "SMESH");
292 SUIT_DataOwnerPtr anIObj (new SalomeApp_DataOwner(aSobj->GetID().c_str()));
294 isValidMesh = mySelectionMgr->isOk(anIObj);
298 _PTR(SObject) aSO = SMESH::FindSObject(myMesh.in());
299 myMeshEdit->setText(aSO->GetName().c_str());
300 myGeomObj = SMESH::GetGeom(aSO);
302 myMeshEdit->setText("");
303 myGeomObj = GEOM::GEOM_Object::_nil();
306 if (myType == Type_2d) {
307 loadFromObject(false);
312 //=======================================================================
313 // function : isValid()
314 // purpose : Verify validity of entry data
315 //=======================================================================
316 bool SMESHGUI_CreatePatternDlg::isValid()
318 if (myGeomObj->_is_nil()) {
319 QMessageBox::information(SMESH::GetDesktop( mySMESHGUI ),
320 tr("SMESH_INSUFFICIENT_DATA"),
321 tr("SMESHGUI_INVALID_PARAMETERS"),
329 //=======================================================================
330 // function : getDefaultName()
331 // purpose : Get default pattern name
332 //=======================================================================
333 QString SMESHGUI_CreatePatternDlg::getDefaultName() const
335 return myType == Type_2d ? tr("DEFAULT_2D") : tr("DEFAULT_3D");
338 //=======================================================================
339 // function : onSave()
340 // purpose : SLOT called when "Save" button pressed. Build pattern and
342 //=======================================================================
343 void SMESHGUI_CreatePatternDlg::onSave()
350 loadFromObject(true);
352 // Load pattern from object
356 ///////////////////////////////////////////////////////
357 SUIT_FileDlg* aDlg = new SUIT_FileDlg (this, false);
358 aDlg->setCaption(tr("SAVE_PATTERN"));
359 aDlg->setMode(QFileDialog::AnyFile);
360 aDlg->setFilters(tr("PATTERN_FILT"));
361 if (myName->text() != "")
362 aDlg->setSelection(myName->text());
364 if (aDlg->exec() != Accepted)
367 QString fName = aDlg->selectedFile();
371 if (QFileInfo(fName).extension().isEmpty())
372 fName = autoExtension(fName);
374 fName = QDir::convertSeparators(fName);
376 QString aData (myPattern->GetString());
377 long aLen = aData.length();
380 aFile.open(IO_WriteOnly);
381 long aWritten = aFile.writeBlock(aData, aLen);
384 if (aWritten != aLen) {
385 QMessageBox::information(SMESH::GetDesktop( mySMESHGUI ), tr("SMESH_ERROR"),
386 tr("ERROR_OF_SAVING"), QMessageBox::Ok);
388 //SUIT_Application::getDesktop()->setSelectionModes(ActorSelection);
389 myViewWindow->SetSelectionMode(ActorSelection);
390 disconnect(mySelectionMgr, 0, this, 0);
391 disconnect(mySMESHGUI, 0, this, 0);
392 mySMESHGUI->ResetState();
396 } catch (const SALOME::SALOME_Exception& S_ex) {
397 SalomeApp_Tools::QtCatchCorbaException(S_ex);
402 //=======================================================================
403 // function : GetPatternName()
404 // purpose : Get name of pattern
405 //=======================================================================
406 QString SMESHGUI_CreatePatternDlg::GetPatternName() const
408 return myName->text();
411 //=======================================================================
412 // function : GetPattern()
413 // purpose : Get result pattern
414 //=======================================================================
415 SMESH::SMESH_Pattern_ptr SMESHGUI_CreatePatternDlg::GetPattern()
417 return myPattern.in();
420 //=======================================================================
422 // purpose : SLOT called when "Ok" button pressed.
423 //=======================================================================
424 void SMESHGUI_CreatePatternDlg::onOk()
431 loadFromObject(true);
433 // Load pattern from object
437 //SUIT_Application::getDesktop()->setSelectionModes(ActorSelection);
438 myViewWindow->SetSelectionMode(ActorSelection);
439 disconnect(mySelectionMgr, 0, this, 0);
440 disconnect(mySMESHGUI, 0, this, 0);
441 mySMESHGUI->ResetState();
445 } catch (const SALOME::SALOME_Exception& S_ex) {
446 SalomeApp_Tools::QtCatchCorbaException(S_ex);
451 //=======================================================================
452 // function : onClose()
453 // purpose : SLOT called when "Close" button pressed. Close dialog
454 //=======================================================================
455 void SMESHGUI_CreatePatternDlg::onClose()
457 myViewWindow->SetSelectionMode(ActorSelection);
458 disconnect(mySelectionMgr, 0, this, 0);
459 disconnect(mySMESHGUI, 0, this, 0);
460 mySMESHGUI->ResetState();
465 //=======================================================================
466 // function : loadFromObject()
467 // purpose : Load pattern from geom object corresponding to the mesh/submesh
468 //=======================================================================
469 bool SMESHGUI_CreatePatternDlg::loadFromObject (const bool theMess)
474 if (myPattern->_is_nil())
475 myPattern = SMESH::GetPattern();
477 if (myMesh->_is_nil() && mySubMesh->_is_nil() || myGeomObj->_is_nil())
480 SMESH::SMESH_Mesh_ptr aMesh = mySubMesh->_is_nil() ? myMesh.in() : mySubMesh->GetFather();
482 myIsLoaded = myType == Type_2d
483 ? myPattern->LoadFromFace(aMesh, myGeomObj, myProjectChk->isChecked())
484 : myPattern->LoadFrom3DBlock(aMesh, myGeomObj);
486 if (!myIsLoaded && theMess) {
488 SMESH::SMESH_Pattern::ErrorCode aCode = myPattern->GetErrorCode();
490 if (aCode == SMESH::SMESH_Pattern::ERR_LOAD_EMPTY_SUBMESH ) aMess = tr("ERR_LOAD_EMPTY_SUBMESH");
491 else if (aCode == SMESH::SMESH_Pattern::ERR_LOADF_NARROW_FACE ) aMess = tr("ERR_LOADF_NARROW_FACE");
492 else if (aCode == SMESH::SMESH_Pattern::ERR_LOADF_CLOSED_FACE ) aMess = tr("ERR_LOADF_CLOSED_FACE");
493 else if (aCode == SMESH::SMESH_Pattern::ERR_LOADV_BAD_SHAPE ) aMess = tr("ERR_LOADV_BAD_SHAPE");
494 else if (aCode == SMESH::SMESH_Pattern::ERR_LOADV_COMPUTE_PARAMS) aMess = tr("ERR_LOADV_COMPUTE_PARAMS");
495 else aMess = tr("ERROR_OF_CREATION");
497 QMessageBox::information(SMESH::GetDesktop( mySMESHGUI ),
498 tr("SMESH_ERROR"), aMess, QMessageBox::Ok);
500 } catch (const SALOME::SALOME_Exception& S_ex) {
501 SalomeApp_Tools::QtCatchCorbaException(S_ex);
507 //=======================================================================
508 // function : onSelectionDone()
509 // purpose : SLOT called when selection changed
510 //=======================================================================
511 void SMESHGUI_CreatePatternDlg::onSelectionDone()
515 mySelectionMgr->selectedObjects(aList, SVTK_Viewer::Type());
516 if (aList.Extent() != 1)
519 // Get mesh or sub-mesh from selection
520 Handle(SALOME_InteractiveObject) anIO = aList.First();
521 SMESH::SMESH_Mesh_var aMesh = SMESH::IObjectToInterface<SMESH::SMESH_Mesh>(anIO);
522 SMESH::SMESH_subMesh_var aSubMesh = SMESH::IObjectToInterface<SMESH::SMESH_subMesh>(anIO);
523 if (aMesh->_is_nil() && aSubMesh->_is_nil())
526 // Get geom object corresponding to the mesh
528 if (!aMesh->_is_nil())
529 aSO = SMESH::FindSObject(aMesh.in());
531 aSO = SMESH::FindSObject(aSubMesh.in());
533 GEOM::GEOM_Object_var aGeomObj = SMESH::GetGeom(aSO);
534 if (aGeomObj->_is_nil())
537 myGeomObj = aGeomObj;
540 if (!aMesh->_is_nil()) {
542 mySubMesh = SMESH::SMESH_subMesh::_nil();
544 mySubMesh = aSubMesh;
545 myMesh = SMESH::SMESH_Mesh::_nil();
549 SMESH::GetNameOfSelectedIObjects(mySelectionMgr, aName);
550 myMeshEdit->setText(aName);
552 if (myType == Type_2d) {
553 loadFromObject(true);
557 myMesh = SMESH::SMESH_Mesh::_nil();
558 mySubMesh = SMESH::SMESH_subMesh::_nil();
559 myGeomObj = GEOM::GEOM_Object::_nil();
564 //=======================================================================
565 // function : onDeactivate()
566 // purpose : SLOT called when dialog must be deativated
567 //=======================================================================
568 void SMESHGUI_CreatePatternDlg::onDeactivate()
570 disconnect(mySelectionMgr, 0, this, 0);
574 //=======================================================================
575 // function : enterEvent()
576 // purpose : Event filter
577 //=======================================================================
578 void SMESHGUI_CreatePatternDlg::enterEvent (QEvent*)
580 mySMESHGUI->EmitSignalDeactivateDialog();
583 connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
586 //=================================================================================
587 // function : closeEvent()
588 // purpose : Close dialog box
589 //=================================================================================
590 void SMESHGUI_CreatePatternDlg::closeEvent (QCloseEvent*)
595 //=======================================================================
596 // function : onSelBtnClicked()
597 // purpose : SLOT. Called when -> button clicked.
598 //=======================================================================
599 void SMESHGUI_CreatePatternDlg::onSelBtnClicked()
604 //================================================================
605 // function : autoExtension()
606 // purpose : Append extension to the file name
607 //================================================================
608 QString SMESHGUI_CreatePatternDlg::autoExtension (const QString& theFileName) const
610 QString anExt = theFileName.section('.', -1);
611 return anExt != "smp" && anExt != "SMP" ? theFileName + ".smp" : theFileName;
614 //=======================================================================
615 // function : displayPreview()
616 // purpose : Display preview
617 //=======================================================================
618 void SMESHGUI_CreatePatternDlg::displayPreview()
620 // Redisplay preview in dialog
625 SMESH::point_array_var pnts = myPattern->GetPoints();
626 SMESH::long_array_var keyPoints = myPattern->GetKeyPoints();
627 SMESH::array_of_long_array_var elemPoints = myPattern->GetElementPoints(false);
629 if (pnts->length() == 0 ||
630 keyPoints->length() == 0 ||
631 elemPoints->length() == 0) {
637 PointVector aPoints (pnts->length());
638 QValueVector<int> aKeyPoints (keyPoints->length());
639 ConnectivityVector anElemPoints (elemPoints->length());
641 for (int i = 0, n = pnts->length(); i < n; i++)
642 aPoints[ i ] = pnts[ i ];
644 for (int i2 = 0, n2 = keyPoints->length(); i2 < n2; i2++)
645 aKeyPoints[ i2 ] = keyPoints[ i2 ];
647 for (int i3 = 0, n3 = elemPoints->length(); i3 < n3; i3++) {
648 QValueVector<int> aVec (elemPoints[ i3 ].length());
649 for (int i4 = 0, n4 = elemPoints[ i3 ].length(); i4 < n4; i4++)
650 aVec[ i4 ] = elemPoints[ i3 ][ i4 ];
652 anElemPoints[ i3 ] = aVec;
655 myPicture2d->SetPoints(aPoints, aKeyPoints, anElemPoints);
660 } catch (const SALOME::SALOME_Exception& S_ex) {
661 SalomeApp_Tools::QtCatchCorbaException(S_ex);
667 //=======================================================================
668 // function : erasePreview()
669 // purpose : Erase preview
670 //=======================================================================
671 void SMESHGUI_CreatePatternDlg::erasePreview()
673 // Erase preview in 2D viewer
674 myPicture2d->SetPoints(PointVector(), QValueVector<int>(), ConnectivityVector());
677 //=======================================================================
678 // function : activateSelection()
679 // purpose : Activate selection in accordance with current pattern type
680 //=======================================================================
681 void SMESHGUI_CreatePatternDlg::activateSelection()
683 mySelectionMgr->clearFilters();
684 //SUIT_Application::getDesktop()->setSelectionModes(ActorSelection);
685 myViewWindow->SetSelectionMode(ActorSelection);
687 if (myType == Type_2d) {
688 mySelectionMgr->installFilter(new SMESH_NumberFilter
689 ("SMESH", TopAbs_SHAPE, -1, TopAbs_FACE));
691 TColStd_MapOfInteger aTypes;
692 aTypes.Add(TopAbs_SHELL);
693 aTypes.Add(TopAbs_SOLID);
694 mySelectionMgr->installFilter(new SMESH_NumberFilter
695 ("SMESH", TopAbs_FACE, 6, aTypes, GEOM::GEOM_Object::_nil(), true));
699 //=======================================================================
700 // function : onTypeChanged()
701 // purpose : SLOT. Called when pattern type changed.
702 // Change dialog's look and feel
703 //=======================================================================
704 void SMESHGUI_CreatePatternDlg::onTypeChanged (int theType)
706 if (myType == theType)
711 if (theType == Type_2d)