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_WhatIsDlg.cxx
24 // Author : Vladimir TURIN, Open CASCADE S.A.S.
27 #include "SMESHGUI_WhatIsDlg.h"
30 #include "SMESHGUI_Utils.h"
31 #include "SMESHGUI_VTKUtils.h"
32 #include "SMESHGUI_MeshUtils.h"
33 #include "SMESHGUI_IdValidator.h"
35 #include "SMESH_Actor.h"
36 #include "SMESH_TypeFilter.hxx"
37 #include "SMESH_LogicalFilter.hxx"
38 #include "SMDS_Mesh.hxx"
39 #include "SMDS_VolumeTool.hxx"
41 // SALOME GUI includes
42 #include <SUIT_Desktop.h>
43 #include <SUIT_ResourceMgr.h>
44 #include <SUIT_Session.h>
45 #include <SUIT_MessageBox.h>
47 #include <LightApp_Application.h>
48 #include <LightApp_SelectionMgr.h>
50 #include <SVTK_ViewModel.h>
51 #include <SVTK_Selection.h>
52 #include <SVTK_ViewWindow.h>
53 #include <SALOME_ListIO.hxx>
54 #include <SALOME_ListIteratorOfListIO.hxx>
57 #include <TColStd_MapOfInteger.hxx>
61 #include <QButtonGroup>
65 #include <QPushButton>
66 #include <QRadioButton>
67 #include <QTextBrowser>
68 #include <QHBoxLayout>
69 #include <QVBoxLayout>
70 #include <QGridLayout>
74 #include <SALOMEconfig.h>
75 #include CORBA_SERVER_HEADER(SMESH_Group)
80 //=================================================================================
81 // class : SMESHGUI_WhatIsDlg()
83 //=================================================================================
84 SMESHGUI_WhatIsDlg::SMESHGUI_WhatIsDlg( SMESHGUI* theModule )
85 : QDialog( SMESH::GetDesktop( theModule ) ),
86 mySMESHGUI( theModule ),
87 mySelectionMgr( SMESH::GetSelectionMgr( theModule ) )
90 setAttribute( Qt::WA_DeleteOnClose, true );
91 setWindowTitle(tr("SMESH_WHAT_IS_TITLE"));
92 setSizeGripEnabled(true);
93 QVBoxLayout* SMESHGUI_WhatIsDlgLayout = new QVBoxLayout(this);
94 SMESHGUI_WhatIsDlgLayout->setSpacing(SPACING);
95 SMESHGUI_WhatIsDlgLayout->setMargin(MARGIN);
97 /***************************************************************/
98 GroupMesh = new QGroupBox(this);
99 QHBoxLayout* GroupMeshLayout = new QHBoxLayout(GroupMesh);
100 GroupMeshLayout->setSpacing(SPACING);
101 GroupMeshLayout->setMargin(MARGIN);
103 MeshLabel = new QLabel(tr("SMESH_NAME"), GroupMesh);
104 GroupMeshLayout->addWidget(MeshLabel);
105 MeshName = new QLineEdit(GroupMesh);
106 MeshName->setReadOnly(true);
107 GroupMeshLayout->addWidget(MeshName);
109 /***************************************************************/
110 GroupSelections = new QGroupBox(tr("ENTITY_TYPE"), this);
111 QButtonGroup* GroupSel = new QButtonGroup(this);
112 QHBoxLayout* GroupSelectionsLayout = new QHBoxLayout(GroupSelections);
113 GroupSelectionsLayout->setSpacing(SPACING);
114 GroupSelectionsLayout->setMargin(MARGIN);
116 RadioButtonNodes = new QRadioButton(tr("SMESH_NODES"), GroupSelections);
117 GroupSelectionsLayout->addWidget(RadioButtonNodes);
118 GroupSel->addButton(RadioButtonNodes, 0);
119 RadioButtonElements = new QRadioButton(tr("SMESH_ELEMENTS"), GroupSelections);
120 GroupSelectionsLayout->addWidget(RadioButtonElements);
121 GroupSel->addButton(RadioButtonElements, 1);
123 /***************************************************************/
124 GroupArguments = new QGroupBox(tr("SMESH_INFORMATION"), this);
125 QGridLayout* GroupArgumentsLayout = new QGridLayout(GroupArguments);
126 GroupArgumentsLayout->setSpacing(SPACING);
127 GroupArgumentsLayout->setMargin(MARGIN);
129 // Controls for elements selection
130 TextLabelElements = new QLabel(tr("SMESH_ID_ELEMENTS"), GroupArguments);
131 GroupArgumentsLayout->addWidget(TextLabelElements, 0, 0);
133 LineEditElements = new QLineEdit(GroupArguments);
134 LineEditElements->setValidator(new SMESHGUI_IdValidator(this));
135 GroupArgumentsLayout->addWidget(LineEditElements, 0, 1);
137 // information text browser
138 Info = new QTextBrowser(GroupArguments);
139 Info->setMinimumSize(300, 200);
140 GroupArgumentsLayout->addWidget(Info, 1, 0, 1, 2);
142 /***************************************************************/
143 GroupButtons = new QGroupBox(this);
144 QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons);
145 GroupButtonsLayout->setSpacing(SPACING);
146 GroupButtonsLayout->setMargin(MARGIN);
148 buttonOk = new QPushButton(tr("SMESH_BUT_OK"), GroupButtons);
149 buttonOk->setAutoDefault(true);
150 buttonOk->setDefault(true);
151 buttonHelp = new QPushButton(tr("SMESH_BUT_HELP"), GroupButtons);
152 buttonHelp->setAutoDefault(true);
154 GroupButtonsLayout->addWidget(buttonOk);
155 GroupButtonsLayout->addSpacing(10);
156 GroupButtonsLayout->addStretch();
157 GroupButtonsLayout->addWidget(buttonHelp);
159 SMESHGUI_WhatIsDlgLayout->addWidget(GroupMesh);
160 SMESHGUI_WhatIsDlgLayout->addWidget(GroupSelections);
161 SMESHGUI_WhatIsDlgLayout->addWidget(GroupArguments);
162 SMESHGUI_WhatIsDlgLayout->addWidget(GroupButtons);
164 RadioButtonNodes->setChecked(true);
166 mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
168 mySMESHGUI->SetActiveDialogBox((QDialog*)this);
170 // Costruction of the logical filter
171 SMESH_TypeFilter* aMeshOrSubMeshFilter = new SMESH_TypeFilter (MESHorSUBMESH);
172 SMESH_TypeFilter* aSmeshGroupFilter = new SMESH_TypeFilter (GROUP);
174 QList<SUIT_SelectionFilter*> aListOfFilters;
175 if (aMeshOrSubMeshFilter) aListOfFilters.append(aMeshOrSubMeshFilter);
176 if (aSmeshGroupFilter) aListOfFilters.append(aSmeshGroupFilter);
178 myMeshOrSubMeshOrGroupFilter =
179 new SMESH_LogicalFilter(aListOfFilters, SMESH_LogicalFilter::LO_OR);
181 myHelpFileName = "mesh_infos_page.html#mesh_element_info_anchor";
185 /* signals and slots connections */
186 connect(buttonOk, SIGNAL(clicked()), this, SLOT(ClickOnOk()));
187 connect(buttonHelp, SIGNAL(clicked()), this, SLOT(ClickOnHelp()));
188 connect(GroupSel, SIGNAL(buttonClicked(int)), SLOT(SelectionsClicked(int)));
190 connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
191 connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
192 /* to close dialog if study change */
193 connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), this, SLOT(ClickOnCancel()));
194 connect(LineEditElements, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
196 SelectionsClicked(0);
197 SelectionIntoArgument();
200 //=================================================================================
201 // function : ~SMESHGUI_WhatIsDlg()
202 // purpose : Destroys the object and frees any allocated resources
203 //=================================================================================
204 SMESHGUI_WhatIsDlg::~SMESHGUI_WhatIsDlg()
208 //=================================================================================
211 //=================================================================================
212 void SMESHGUI_WhatIsDlg::Init (bool ResetControls)
216 LineEditElements->clear();
219 myMesh = SMESH::SMESH_Mesh::_nil();
222 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
223 aViewWindow->SetSelectionMode( CellSelection );
224 onTextChange(LineEditElements->text());
226 SelectionIntoArgument();
230 //=================================================================================
231 // function : SelectionsClicked()
232 // purpose : Radio button management
233 //=================================================================================
234 void SMESHGUI_WhatIsDlg::SelectionsClicked (int selectionId)
236 disconnect(mySelectionMgr, 0, this, 0);
238 mySelectionMgr->clearFilters();
240 switch (selectionId) {
243 SMESH::SetPointRepresentation(true);
244 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
245 aViewWindow->SetSelectionMode( NodeSelection );
250 SMESH::SetPointRepresentation(false);
251 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
252 aViewWindow->SetSelectionMode( CellSelection );
257 connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
258 SelectionIntoArgument();
261 //=================================================================================
262 // function : ClickOnOk()
264 //=================================================================================
265 void SMESHGUI_WhatIsDlg::ClickOnOk()
267 if (mySMESHGUI->isActiveStudyLocked())
272 SelectionIntoArgument();
276 //=================================================================================
277 // function : ClickOnCancel()
279 //=================================================================================
280 void SMESHGUI_WhatIsDlg::ClickOnCancel()
282 disconnect(mySelectionMgr, 0, this, 0);
283 mySelectionMgr->clearFilters();
284 SMESH::SetPointRepresentation(false);
285 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
286 aViewWindow->SetSelectionMode( ActorSelection );
287 mySMESHGUI->ResetState();
291 //=================================================================================
292 // function : ClickOnHelp()
294 //=================================================================================
295 void SMESHGUI_WhatIsDlg::ClickOnHelp()
297 LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
299 app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
301 SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
302 tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
303 arg(app->resourceMgr()->stringValue("ExternalBrowser",
305 arg(myHelpFileName));
309 //=======================================================================
310 // function : onTextChange()
312 //=======================================================================
313 void SMESHGUI_WhatIsDlg::onTextChange (const QString& theNewText)
318 // hilight entered elements
319 SMDS_Mesh* aMesh = 0;
321 aMesh = myActor->GetObject()->GetMesh();
324 Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
326 TColStd_MapOfInteger newIndices;
328 QStringList aListId = theNewText.split(" ", QString::SkipEmptyParts);
330 for (int i = 0; i < aListId.count(); i++) {
331 const SMDS_MeshElement * e = RadioButtonNodes->isChecked()?
332 aMesh->FindNode(aListId[ i ].toInt()):
333 aMesh->FindElement(aListId[ i ].toInt());
335 newIndices.Add(e->GetID());
338 mySelector->AddOrRemoveIndex( anIO, newIndices, false );
339 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
340 aViewWindow->highlight( anIO, true, true );
343 SelectionIntoArgument();
348 //=================================================================================
349 // function : SelectionIntoArgument()
350 // purpose : Called when selection as changed or other case
351 //=================================================================================
352 void SMESHGUI_WhatIsDlg::SelectionIntoArgument()
354 int curBusy = myBusy;
358 QString aString = "";
362 LineEditElements->setText(aString);
363 MeshName->setText(aString);
364 GroupMesh->setTitle(tr(""));
368 if (!GroupButtons->isEnabled()) // inactive
373 mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type());
375 int nbSel = aList.Extent();
380 Handle(SALOME_InteractiveObject) IO = aList.First();
381 myMesh = SMESH::GetMeshByIO(IO);
382 if (myMesh->_is_nil())
386 //check if all selected objects belongs to one mesh
387 SALOME_ListIteratorOfListIO io( aList );
388 for (io.Next(); io.More(); io.Next() ) {
389 SMESH::SMESH_Mesh_var mesh = SMESH::GetMeshByIO(io.Value());
390 if (!mesh->_is_nil() && !mesh->_is_equivalent( myMesh ))
393 // select IO with any element selected (for case of selection by rectangle)
395 for (io.Initialize(aList); io.More() && IO.IsNull(); io.Next() )
396 if ( mySelector->HasIndex( io.Value() ))
398 if ( IO.IsNull() ) return;
400 if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) {
401 for (io.Initialize(aList); io.More(); io.Next() )
402 if ( !IO->isSame( io.Value() ))
403 aViewWindow->highlight( io.Value(), false, true );
407 myActor = SMESH::FindActorByObject(myMesh);
409 myActor = SMESH::FindActorByEntry(IO->getEntry());
413 QString aName = IO->getName();
414 // cut off wite spaces from tail, else meaningful head is not visible
415 int size = aName.length();
416 while (size && aName.at(size-1).isSpace() )
418 if ( size != aName.length() )
419 aName.truncate( size );
420 MeshName->setText(aName); // can be something like "2 objects"
422 if(!SMESH::IObjectToInterface<SMESH::SMESH_Mesh>(IO)->_is_nil()) {
423 GroupMesh->setTitle(tr("SMESH_MESH"));
424 } else if(!SMESH::IObjectToInterface<SMESH::SMESH_subMesh>(IO)->_is_nil()) {
425 GroupMesh->setTitle(tr("SMESH_SUBMESH"));
426 } else if(!SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>(IO)->_is_nil()) {
427 GroupMesh->setTitle(tr("SMESH_GROUP"));
432 aNbUnits = SMESH::GetNameOfSelectedElements(mySelector, IO, aString);
437 const SMDS_MeshElement * e = RadioButtonNodes->isChecked()?
438 myActor->GetObject()->GetMesh()->FindNode(aString.toInt()):
439 myActor->GetObject()->GetMesh()->FindElement(aString.toInt());
442 anInfo="<b>" + tr("ENTITY_TYPE") + ":</b> ";
443 if(e->GetType() == SMDSAbs_Node) {
444 anInfo+=tr("MESH_NODE")+"<br>";
445 //const SMDS_MeshNode *en = (SMDS_MeshNode*) e; // VSR: not used!
446 } else if(e->GetType() == SMDSAbs_Edge) {
447 anInfo+=tr("SMESH_EDGE")+"<br>";
448 anInfo+="<b>" + tr("SMESH_MESHINFO_TYPE")+":</b> ";
449 const SMDS_MeshEdge *ee = (SMDS_MeshEdge*) e;
450 anInfo+=(ee->IsQuadratic()?tr("SMESH_MESHINFO_ORDER2"):tr("SMESH_MESHINFO_ORDER1"))+"<br>";
451 } else if(e->GetType() == SMDSAbs_Face) {
452 const SMDS_MeshFace *ef = (SMDS_MeshFace*) e;
453 anInfo+=tr("SMESH_FACE")+"<br>";
454 anInfo+="<b>" + tr("SMESH_MESHINFO_TYPE")+":</b> ";
456 anInfo+=(ef->IsQuadratic()?tr("SMESH_MESHINFO_ORDER2"):tr("SMESH_MESHINFO_ORDER1"))+" ";
457 switch(ef->NbNodes()) {
461 anInfo+=tr("SMESH_TRIANGLE");
467 anInfo+=tr("SMESH_QUADRANGLE");
474 } else if(e->GetType() == SMDSAbs_Volume) {
475 anInfo+=tr("SMESH_VOLUME")+"<br>";
476 anInfo+="<b>" + tr("SMESH_MESHINFO_TYPE")+":</b> ";
477 const SMDS_MeshVolume *ev = (SMDS_MeshVolume*) e;
478 SMDS_VolumeTool vt(ev);
479 if(vt.GetVolumeType() != SMDS_VolumeTool::POLYHEDA)
480 anInfo+=(ev->IsQuadratic()?tr("SMESH_MESHINFO_ORDER2"):tr("SMESH_MESHINFO_ORDER1"))+" ";
481 switch(vt.GetVolumeType()) {
482 case SMDS_VolumeTool::TETRA:
483 case SMDS_VolumeTool::QUAD_TETRA:
485 anInfo+=tr("SMESH_TETRAS");
488 case SMDS_VolumeTool::PYRAM:
489 case SMDS_VolumeTool::QUAD_PYRAM:
491 anInfo+=tr("SMESH_PYRAMID");
494 case SMDS_VolumeTool::PENTA:
495 case SMDS_VolumeTool::QUAD_PENTA:
497 anInfo+=tr("SMESH_PRISM");
500 case SMDS_VolumeTool::HEXA:
501 case SMDS_VolumeTool::QUAD_HEXA:
503 anInfo+=tr("SMESH_HEXAS");
506 case SMDS_VolumeTool::POLYHEDA:
508 anInfo+=tr("SMESH_POLYEDRON");
516 gp_XYZ anXYZ(0.,0.,0.);
517 SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
519 QString aNodesInfo="";
520 for( ; nodeIt->more(); nbNodes++) {
521 const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
522 anXYZ.Add( gp_XYZ( node->X(), node->Y(), node->Z() ) );
523 if(e->GetType() != SMDSAbs_Node)
524 aNodesInfo+=QString("<b>Node %1:</b><br>Id=%2, X=%3, Y=%4, Z=%5<br>").arg(nbNodes+1).arg(node->GetID()).arg(node->X()).arg(node->Y()).arg(node->Z());
525 // Calculate Connectivity
526 SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
528 aNodesInfo+="<b>" + tr("CONNECTED_ELEMENTS") + ":</b>";
530 const SMDS_MeshElement* elem = it->next();
531 aNodesInfo+=QString(" %1").arg(elem->GetID());
533 if ( (nbNodes+1) != e->NbNodes())
534 aNodesInfo+=QString("<br><br>");
537 if(e->GetType() != SMDSAbs_Node)
538 anInfo+="<b>" + tr("GRAVITY_CENTER") + ":</b><br>";
539 anXYZ.Divide(e->NbNodes());
540 anInfo+=QString("X=%1, Y=%2, Z=%3").arg(anXYZ.X()).arg(anXYZ.Y()).arg(anXYZ.Z());
541 if(e->GetType() != SMDSAbs_Node)
544 anInfo+= "<br>" + aNodesInfo;
545 Info->setText(anInfo);
550 LineEditElements->setText(aString);
555 //=================================================================================
556 // function : DeactivateActiveDialog()
558 //=================================================================================
559 void SMESHGUI_WhatIsDlg::DeactivateActiveDialog()
561 if (GroupArguments->isEnabled()) {
562 GroupSelections->setEnabled(false);
563 GroupMesh->setEnabled(false);
564 GroupArguments->setEnabled(false);
565 GroupButtons->setEnabled(false);
566 mySMESHGUI->ResetState();
567 mySMESHGUI->SetActiveDialogBox(0);
571 //=================================================================================
572 // function : ActivateThisDialog()
574 //=================================================================================
575 void SMESHGUI_WhatIsDlg::ActivateThisDialog()
577 /* Emit a signal to deactivate the active dialog */
578 mySMESHGUI->EmitSignalDeactivateDialog();
579 GroupArguments->setEnabled(true);
580 GroupButtons->setEnabled(true);
581 GroupSelections->setEnabled(true);
582 GroupMesh->setEnabled(true);
584 mySMESHGUI->SetActiveDialogBox((QDialog*)this);
586 if ( SMESH::GetViewWindow( mySMESHGUI ))
587 SelectionsClicked(RadioButtonNodes->isChecked()?0:1);
589 SelectionIntoArgument();
592 //=================================================================================
593 // function : enterEvent()
595 //=================================================================================
596 void SMESHGUI_WhatIsDlg::enterEvent (QEvent*)
598 if (!GroupArguments->isEnabled())
599 ActivateThisDialog();
602 //=================================================================================
603 // function : closeEvent()
605 //=================================================================================
606 void SMESHGUI_WhatIsDlg::closeEvent (QCloseEvent*)
608 /* same than click on cancel button */
612 //=======================================================================
613 //function : hideEvent
614 //purpose : caused by ESC key
615 //=======================================================================
616 void SMESHGUI_WhatIsDlg::hideEvent (QHideEvent*)
622 //=================================================================================
623 // function : keyPressEvent()
625 //=================================================================================
626 void SMESHGUI_WhatIsDlg::keyPressEvent( QKeyEvent* e )
628 QDialog::keyPressEvent( e );
629 if ( e->isAccepted() )
632 if ( e->key() == Qt::Key_F1 ) {