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_AddMeshElementDlg.cxx
25 // Author : Nicolas REJNERI
29 #include "SMESHGUI_AddMeshElementDlg.h"
32 #include "SMESHGUI_Utils.h"
33 #include "SMESHGUI_VTKUtils.h"
34 #include "SMESHGUI_MeshUtils.h"
35 #include "SMESHGUI_IdValidator.h"
36 #include "SMESH_ActorUtils.h"
38 #include "SMDS_Mesh.hxx"
39 #include "SMESH_Actor.h"
41 #include "SUIT_Session.h"
43 #include "SVTK_Selection.h"
44 #include "SVTK_Selector.h"
45 #include "SALOME_ListIO.hxx"
46 #include "SALOME_ListIteratorOfListIO.hxx"
48 #include "SalomeApp_Study.h"
49 #include "SalomeApp_Application.h"
51 #include "SVTK_ViewModel.h"
52 #include "SVTK_ViewWindow.h"
54 #include "utilities.h"
57 #include <TColStd_MapOfInteger.hxx>
58 #include <TColStd_IndexedMapOfInteger.hxx>
62 #include <vtkIdList.h>
63 #include <vtkIntArray.h>
64 #include <vtkCellArray.h>
65 #include <vtkUnsignedCharArray.h>
66 #include <vtkUnstructuredGrid.h>
67 #include <vtkDataSetMapper.h>
70 #include <qbuttongroup.h>
71 #include <qgroupbox.h>
73 #include <qlineedit.h>
74 #include <qpushbutton.h>
75 #include <qradiobutton.h>
79 #include <qwhatsthis.h>
82 #include <qcheckbox.h>
92 class TElementSimulation {
93 SalomeApp_Application* myApplication;
94 SUIT_ViewWindow* myViewWindow;
95 SVTK_ViewWindow* myVTKViewWindow;
97 SALOME_Actor* myPreviewActor;
98 vtkDataSetMapper* myMapper;
99 vtkUnstructuredGrid* myGrid;
102 TElementSimulation (SalomeApp_Application* theApplication)
104 myApplication = theApplication;
105 SUIT_ViewManager* mgr = theApplication->activeViewManager();
107 myViewWindow = mgr->getActiveView();
108 myVTKViewWindow = GetVtkViewWindow(myViewWindow);
110 myGrid = vtkUnstructuredGrid::New();
112 // Create and display actor
113 myMapper = vtkDataSetMapper::New();
114 myMapper->SetInput(myGrid);
116 myPreviewActor = SALOME_Actor::New();
117 myPreviewActor->PickableOff();
118 myPreviewActor->VisibilityOff();
119 myPreviewActor->SetMapper(myMapper);
121 vtkProperty* aProp = vtkProperty::New();
123 anRGB[0] = GetFloat("SMESH:SettingsFillColorRed", 0)/255.;
124 anRGB[1] = GetFloat("SMESH:SettingsFillColorGreen", 170)/255.;
125 anRGB[2] = GetFloat("SMESH:SettingsFillColorBlue", 255)/255.;
126 aProp->SetColor(anRGB[0],anRGB[1],anRGB[2]);
127 myPreviewActor->SetProperty(aProp);
130 vtkProperty* aBackProp = vtkProperty::New();
131 anRGB[0] = GetFloat("SMESH:SettingsBackFaceColorRed", 0)/255.;
132 anRGB[1] = GetFloat("SMESH:SettingsBackFaceColorGreen", 0)/255.;
133 anRGB[2] = GetFloat("SMESH:SettingsBackFaceColorBlue", 255)/255.;
134 aBackProp->SetColor(anRGB[0],anRGB[1],anRGB[2]);
135 myPreviewActor->SetBackfaceProperty(aBackProp);
138 myVTKViewWindow->AddActor(myPreviewActor);
141 typedef std::vector<vtkIdType> TVTKIds;
142 void SetPosition (SMESH_Actor* theActor,
144 const TVTKIds& theIds)
146 vtkUnstructuredGrid *aGrid = theActor->GetUnstructuredGrid();
147 myGrid->SetPoints(aGrid->GetPoints());
149 const int* aConn = NULL;
153 static int anIds[] = {0,2,1,3};
159 static int anIds[] = {0,3,2,1,4};
165 static int anIds[] = {0,3,2,1,4,7,6,5};
172 vtkIdList *anIds = vtkIdList::New();
175 for (int i = 0, iEnd = theIds.size(); i < iEnd; i++)
176 anIds->InsertId(i,theIds[aConn[i]]);
178 for (int i = 0, iEnd = theIds.size(); i < iEnd; i++)
179 anIds->InsertId(i,theIds[i]);
181 myGrid->InsertNextCell(theType,anIds);
190 void SetVisibility (bool theVisibility)
192 myPreviewActor->SetVisibility(theVisibility);
193 RepaintCurrentView();
197 ~TElementSimulation()
199 if (FindVtkViewWindow(myApplication->activeViewManager(), myViewWindow)) {
200 myVTKViewWindow->RemoveActor(myPreviewActor);
202 myPreviewActor->Delete();
204 myMapper->RemoveAllInputs();
212 //=================================================================================
213 // function : SMESHGUI_AddMeshElementDlg()
214 // purpose : constructor
215 //=================================================================================
216 SMESHGUI_AddMeshElementDlg::SMESHGUI_AddMeshElementDlg( SMESHGUI* theModule,
218 SMDSAbs_ElementType ElementType, int nbNodes,
219 bool modal, WFlags fl)
220 : QDialog( SMESH::GetDesktop( theModule ), name, modal, WStyle_Customize | WStyle_NormalBorder |
221 WStyle_Title | WStyle_SysMenu | Qt::WDestructiveClose),
222 mySMESHGUI( theModule ),
223 mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ),
224 myViewWindow( SMESH::GetViewWindow( theModule ) ),
225 mySelector( myViewWindow->GetSelector() )
227 SalomeApp_Application* anApp = dynamic_cast<SalomeApp_Application*>
228 (SUIT_Session::session()->activeApplication());
230 mySimulation = new SMESH::TElementSimulation (anApp);
232 // verify nb nodes and type
234 myElementType = ElementType;
235 switch (ElementType) {
237 // if (myNbNodes != 3 && myNbNodes != 4)
241 // if (myNbNodes != 4 && myNbNodes != 8) //(nbNodes < 4 || nbNodes > 8 || nbNodes == 7)
245 myElementType = SMDSAbs_Edge;
252 else if (myNbNodes == 3)
253 elemName = "TRIANGLE";
254 else if (myNbNodes == 4)
255 if (myElementType == SMDSAbs_Face)
256 elemName = "QUADRANGLE";
259 else if (myNbNodes == 8)
261 else if (myElementType == SMDSAbs_Face){
262 elemName = "POLYGON";
266 QString iconName = tr(QString("ICON_DLG_%1").arg(elemName));
267 QString buttonGrTitle = tr(QString("SMESH_%1").arg(elemName));
268 QString caption = tr(QString("SMESH_ADD_%1_TITLE").arg(elemName));
269 QString grBoxTitle = tr(QString("SMESH_ADD_%1").arg(elemName));
271 QPixmap image0 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", iconName));
272 QPixmap image1 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
275 setName("SMESHGUI_AddMeshElementDlg");
279 setSizeGripEnabled(TRUE);
280 SMESHGUI_AddMeshElementDlgLayout = new QGridLayout(this);
281 SMESHGUI_AddMeshElementDlgLayout->setSpacing(6);
282 SMESHGUI_AddMeshElementDlgLayout->setMargin(11);
284 /***************************************************************/
285 GroupConstructors = new QButtonGroup(this, "GroupConstructors");
286 GroupConstructors->setTitle(buttonGrTitle);
288 GroupConstructors->setExclusive(TRUE);
289 GroupConstructors->setColumnLayout(0, Qt::Vertical);
290 GroupConstructors->layout()->setSpacing(0);
291 GroupConstructors->layout()->setMargin(0);
292 GroupConstructorsLayout = new QGridLayout(GroupConstructors->layout());
293 GroupConstructorsLayout->setAlignment(Qt::AlignTop);
294 GroupConstructorsLayout->setSpacing(6);
295 GroupConstructorsLayout->setMargin(11);
296 Constructor1 = new QRadioButton(GroupConstructors, "Constructor1");
297 Constructor1->setText(tr("" ));
298 Constructor1->setPixmap(image0);
299 Constructor1->setChecked(TRUE);
300 Constructor1->setSizePolicy(QSizePolicy((QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, Constructor1->sizePolicy().hasHeightForWidth()));
301 Constructor1->setMinimumSize(QSize(50, 0));
302 GroupConstructorsLayout->addWidget(Constructor1, 0, 0);
303 QSpacerItem* spacer = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
304 GroupConstructorsLayout->addItem(spacer, 0, 1);
305 SMESHGUI_AddMeshElementDlgLayout->addWidget(GroupConstructors, 0, 0);
307 /***************************************************************/
308 GroupButtons = new QGroupBox(this, "GroupButtons");
309 GroupButtons->setGeometry(QRect(10, 10, 281, 48));
310 GroupButtons->setTitle(tr("" ));
311 GroupButtons->setColumnLayout(0, Qt::Vertical);
312 GroupButtons->layout()->setSpacing(0);
313 GroupButtons->layout()->setMargin(0);
314 GroupButtonsLayout = new QGridLayout(GroupButtons->layout());
315 GroupButtonsLayout->setAlignment(Qt::AlignTop);
316 GroupButtonsLayout->setSpacing(6);
317 GroupButtonsLayout->setMargin(11);
318 buttonCancel = new QPushButton(GroupButtons, "buttonCancel");
319 buttonCancel->setText(tr("SMESH_BUT_CLOSE" ));
320 buttonCancel->setAutoDefault(TRUE);
321 GroupButtonsLayout->addWidget(buttonCancel, 0, 3);
322 buttonApply = new QPushButton(GroupButtons, "buttonApply");
323 buttonApply->setText(tr("SMESH_BUT_APPLY" ));
324 buttonApply->setAutoDefault(TRUE);
325 GroupButtonsLayout->addWidget(buttonApply, 0, 1);
326 QSpacerItem* spacer_9 = new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
327 GroupButtonsLayout->addItem(spacer_9, 0, 2);
328 buttonOk = new QPushButton(GroupButtons, "buttonOk");
329 buttonOk->setText(tr("SMESH_BUT_OK" ));
330 buttonOk->setAutoDefault(TRUE);
331 buttonOk->setDefault(TRUE);
332 GroupButtonsLayout->addWidget(buttonOk, 0, 0);
333 SMESHGUI_AddMeshElementDlgLayout->addWidget(GroupButtons, 2, 0);
335 /***************************************************************/
336 GroupC1 = new QGroupBox(this, "GroupC1");
337 GroupC1->setTitle(grBoxTitle);
339 GroupC1->setMinimumSize(QSize(0, 0));
340 GroupC1->setFrameShape(QGroupBox::Box);
341 GroupC1->setFrameShadow(QGroupBox::Sunken);
342 GroupC1->setColumnLayout(0, Qt::Vertical);
343 GroupC1->layout()->setSpacing(0);
344 GroupC1->layout()->setMargin(0);
345 GroupC1Layout = new QGridLayout(GroupC1->layout());
346 GroupC1Layout->setAlignment(Qt::AlignTop);
347 GroupC1Layout->setSpacing(6);
348 GroupC1Layout->setMargin(11);
349 TextLabelC1A1 = new QLabel(GroupC1, "TextLabelC1A1");
350 TextLabelC1A1->setText(tr("SMESH_ID_NODES" ));
351 TextLabelC1A1->setMinimumSize(QSize(50, 0));
352 TextLabelC1A1->setFrameShape(QLabel::NoFrame);
353 TextLabelC1A1->setFrameShadow(QLabel::Plain);
354 GroupC1Layout->addWidget(TextLabelC1A1, 0, 0);
355 SelectButtonC1A1 = new QPushButton(GroupC1, "SelectButtonC1A1");
356 SelectButtonC1A1->setText(tr("" ));
357 SelectButtonC1A1->setPixmap(image1);
358 SelectButtonC1A1->setToggleButton(FALSE);
359 GroupC1Layout->addWidget(SelectButtonC1A1, 0, 1);
360 LineEditC1A1 = new QLineEdit(GroupC1, "LineEditC1A1");
361 // LineEditC1A1->setReadOnly(TRUE);
363 LineEditC1A1->setValidator(new SMESHGUI_IdValidator(this, "validator", myNbNodes));
364 GroupC1Layout->addWidget(LineEditC1A1, 0, 2);
366 if (myElementType == SMDSAbs_Face) {
367 Reverse = new QCheckBox(GroupC1, "Reverse");
368 Reverse->setText(tr("SMESH_REVERSE" ));
369 GroupC1Layout->addWidget(Reverse, 1, 0);
374 SMESHGUI_AddMeshElementDlgLayout->addWidget(GroupC1, 1, 0);
376 Init(); /* Initialisations */
379 //=================================================================================
380 // function : ~SMESHGUI_AddMeshElementDlg()
381 // purpose : Destroys the object and frees any allocated resources
382 //=================================================================================
383 SMESHGUI_AddMeshElementDlg::~SMESHGUI_AddMeshElementDlg()
385 // no need to delete child widgets, Qt does it all for us
389 //=================================================================================
392 //=================================================================================
393 void SMESHGUI_AddMeshElementDlg::Init()
396 Constructor1->setChecked(TRUE);
397 myEditCurrentArgument = LineEditC1A1;
398 mySMESHGUI->SetActiveDialogBox((QDialog*)this);
403 /* signals and slots connections */
404 connect(buttonOk, SIGNAL(clicked()), SLOT(ClickOnOk()));
405 connect(buttonCancel, SIGNAL(clicked()), SLOT(ClickOnCancel()));
406 connect(buttonApply, SIGNAL(clicked()), SLOT(ClickOnApply()));
408 connect(SelectButtonC1A1, SIGNAL(clicked()), SLOT(SetEditCurrentArgument()));
409 connect(LineEditC1A1, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
410 connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), SLOT(DeactivateActiveDialog()));
411 connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(SelectionIntoArgument()));
412 /* to close dialog if study frame change */
413 connect(mySMESHGUI, SIGNAL (SignalStudyFrameChanged()), SLOT(ClickOnCancel()));
416 connect(Reverse, SIGNAL(stateChanged(int)), SLOT(CheckBox(int)));
418 // Move widget on the botton right corner of main widget
420 mySMESHGUI->DefineDlgPosition(this, x, y);
422 this->show(); // displays Dialog
424 // set selection mode
425 SMESH::SetPointRepresentation(true);
427 myViewWindow->SetSelectionMode( NodeSelection );
431 SelectionIntoArgument();
434 //=================================================================================
435 // function : ClickOnApply()
437 //=================================================================================
438 void SMESHGUI_AddMeshElementDlg::ClickOnApply()
440 if (myNbOkNodes && !mySMESHGUI->isActiveStudyLocked()) {
442 SMESH::long_array_var anArrayOfIdeces = new SMESH::long_array;
443 anArrayOfIdeces->length(myNbNodes);
444 bool reverse = (Reverse && Reverse->isChecked());
445 QStringList aListId = QStringList::split(" ", myEditCurrentArgument->text(), false);
446 for (int i = 0; i < aListId.count(); i++)
448 anArrayOfIdeces[i] = aListId[ myNbNodes - i - 1 ].toInt();
450 anArrayOfIdeces[i] = aListId[ i ].toInt();
452 SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
453 switch (myElementType) {
455 aMeshEditor->AddEdge(anArrayOfIdeces.inout()); break;
457 aMeshEditor->AddFace(anArrayOfIdeces.inout()); break;
459 aMeshEditor->AddVolume(anArrayOfIdeces.inout()); break;
463 SALOME_ListIO aList; aList.Append( myActor->getIO() );
464 mySelectionMgr->setSelectedObjects( aList, false );
467 mySimulation->SetVisibility(false);
469 buttonOk->setEnabled(false);
470 buttonApply->setEnabled(false);
472 myEditCurrentArgument->setText("");
478 //=================================================================================
479 // function : ClickOnOk()
481 //=================================================================================
482 void SMESHGUI_AddMeshElementDlg::ClickOnOk()
484 this->ClickOnApply();
485 this->ClickOnCancel();
489 //=================================================================================
490 // function : ClickOnCancel()
492 //=================================================================================
493 void SMESHGUI_AddMeshElementDlg::ClickOnCancel()
495 mySelectionMgr->clearSelected();
496 mySimulation->SetVisibility(false);
497 SMESH::SetPointRepresentation(false);
498 myViewWindow->SetSelectionMode( ActorSelection );
499 disconnect(mySelectionMgr, 0, this, 0);
500 mySMESHGUI->ResetState();
505 //=================================================================================
506 // function : onTextChange()
508 //=================================================================================
509 void SMESHGUI_AddMeshElementDlg::onTextChange (const QString& theNewText)
516 buttonOk->setEnabled(false);
517 buttonApply->setEnabled(false);
519 mySimulation->SetVisibility(false);
521 // hilight entered nodes
522 SMDS_Mesh* aMesh = 0;
524 aMesh = myActor->GetObject()->GetMesh();
527 SALOME_ListIO aList; aList.Append( myActor->getIO() );
528 mySelectionMgr->setSelectedObjects( aList, false );
530 TColStd_IndexedMapOfInteger selectedIndices;
531 TColStd_MapOfInteger newIndices;
532 mySelector->GetIndex(myActor->getIO(), selectedIndices);
534 QStringList aListId = QStringList::split(" ", theNewText, false);
535 for (int i = 0; i < aListId.count(); i++) {
536 if( const SMDS_MeshNode * n = aMesh->FindNode( aListId[ i ].toInt() ) )
538 if( selectedIndices.Add( n->GetID() ) )
539 newIndices.Add( n->GetID() );
544 if( newIndices.Extent()>0 )
546 mySelector->AddOrRemoveIndex( myActor->getIO(), newIndices, true );
547 myViewWindow->highlight( myActor->getIO(), true, true );
549 bool aNodesOK = false;
550 if (myIsPoly && myElementType == SMDSAbs_Face && aListId.count() >=3 ){
551 myNbOkNodes = aListId.count();
557 buttonOk->setEnabled(true);
558 buttonApply->setEnabled(true);
565 //=================================================================================
566 // function : SelectionIntoArgument()
567 // purpose : Called when selection has changed
568 //=================================================================================
569 void SMESHGUI_AddMeshElementDlg::SelectionIntoArgument()
578 myEditCurrentArgument->setText("");
581 if (!GroupButtons->isEnabled()) // inactive
584 buttonOk->setEnabled(false);
585 buttonApply->setEnabled(false);
587 mySimulation->SetVisibility(false);
588 // SMESH::SetPointRepresentation(true);
592 mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type());
594 if (aList.Extent() != 1)
597 Handle(SALOME_InteractiveObject) anIO = aList.First();
598 myMesh = SMESH::GetMeshByIO(anIO);
599 if (myMesh->_is_nil())
602 myActor = SMESH::FindActorByEntry(anIO->getEntry());
606 // get selected nodes
607 QString aString = "";
608 int nbNodes = SMESH::GetNameOfSelectedNodes(mySelector,myActor->getIO(),aString);
610 myEditCurrentArgument->setText(aString);
612 if (myIsPoly && myElementType == SMDSAbs_Face && nbNodes >= 3 ) {
614 } else if (myNbNodes != nbNodes) {
619 myNbOkNodes = nbNodes;
621 buttonOk->setEnabled(true);
622 buttonApply->setEnabled(true);
627 //=================================================================================
628 // function : displaySimulation()
630 //=================================================================================
631 void SMESHGUI_AddMeshElementDlg::displaySimulation()
633 if (myNbOkNodes && GroupButtons->isEnabled()) {
634 SMESH::TElementSimulation::TVTKIds anIds;
635 QStringList aListId = QStringList::split(" ", myEditCurrentArgument->text(), false);
636 for (int i = 0; i < aListId.count(); i++)
637 anIds.push_back(myActor->GetObject()->GetNodeVTKId(aListId[ i ].toInt()));
639 if (Reverse && Reverse->isChecked())
640 reverse(anIds.begin(),anIds.end());
644 switch ( myElementType ) {
645 case SMDSAbs_Face : aType = VTK_POLYGON; break;
650 case 2: aType = VTK_LINE; break;
651 case 3: aType = VTK_TRIANGLE; break;
652 case 4: aType = myElementType == SMDSAbs_Face ? VTK_QUAD : VTK_TETRA; break;
653 case 8: aType = VTK_HEXAHEDRON; break;
658 mySimulation->SetPosition(myActor,aType,anIds);
662 //=================================================================================
663 // function : SetEditCurrentArgument()
665 //=================================================================================
666 void SMESHGUI_AddMeshElementDlg::SetEditCurrentArgument()
668 QPushButton* send = (QPushButton*)sender();
669 if (send == SelectButtonC1A1) {
670 LineEditC1A1->setFocus();
671 myEditCurrentArgument = LineEditC1A1;
673 SelectionIntoArgument();
676 //=================================================================================
677 // function : DeactivateActiveDialog()
679 //=================================================================================
680 void SMESHGUI_AddMeshElementDlg::DeactivateActiveDialog()
682 if (GroupConstructors->isEnabled()) {
683 GroupConstructors->setEnabled(false);
684 GroupC1->setEnabled(false);
685 GroupButtons->setEnabled(false);
686 mySimulation->SetVisibility(false);
687 mySMESHGUI->ResetState();
688 mySMESHGUI->SetActiveDialogBox(0);
692 //=================================================================================
693 // function : ActivateThisDialog()
695 //=================================================================================
696 void SMESHGUI_AddMeshElementDlg::ActivateThisDialog()
698 /* Emit a signal to deactivate the active dialog */
699 mySMESHGUI->EmitSignalDeactivateDialog();
701 GroupConstructors->setEnabled(true);
702 GroupC1->setEnabled(true);
703 GroupButtons->setEnabled(true);
705 SMESH::SetPointRepresentation(true);
707 myViewWindow->SetSelectionMode( NodeSelection );
708 SelectionIntoArgument();
711 //=================================================================================
712 // function : enterEvent()
714 //=================================================================================
715 void SMESHGUI_AddMeshElementDlg::enterEvent (QEvent*)
717 if (GroupConstructors->isEnabled())
719 ActivateThisDialog();
723 //=================================================================================
724 // function : closeEvent()
726 //=================================================================================
727 void SMESHGUI_AddMeshElementDlg::closeEvent (QCloseEvent*)
729 /* same than click on cancel button */
730 this->ClickOnCancel();
734 //=================================================================================
735 // function : hideEvent()
736 // purpose : caused by ESC key
737 //=================================================================================
738 void SMESHGUI_AddMeshElementDlg::hideEvent (QHideEvent*)
744 //=================================================================================
745 // function : CheckBox()
747 //=================================================================================
748 void SMESHGUI_AddMeshElementDlg::CheckBox (int state)
754 mySimulation->SetVisibility(false);