X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESHGUI%2FSMESHGUI_ComputeDlg.cxx;h=32b472ff6d3545b5dde30bb5e3e154d896dfb7cb;hp=51d62037b2b8d48617ca9718e9b1787ce568c906;hb=21af9b3a2c317f5693f228cd8ed55c2bb44b0a07;hpb=79b1ac2b6df9117f16f11d444b1f165d477a1813 diff --git a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx index 51d62037b..32b472ff6 100644 --- a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx @@ -1,118 +1,125 @@ -// SMESH SMESHGUI : GUI for SMESH component +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE // -// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. // -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// -// -// File : SMESHGUI_ComputeDlg.cxx -// Author : Edward AGAPOV -// Module : SMESH +// File : SMESHGUI_ComputeDlg.cxx +// Author : Edward AGAPOV, Open CASCADE S.A.S. +// SMESH includes +// #include "SMESHGUI_ComputeDlg.h" +#include "SMDS_Mesh.hxx" +#include "SMDS_SetIterator.hxx" #include "SMESHGUI.h" #include "SMESHGUI_GEOMGenUtils.h" +#include "SMESHGUI_HypothesesUtils.h" +#include "SMESHGUI_MeshEditPreview.h" +#include "SMESHGUI_MeshInfosBox.h" +#include "SMESHGUI_MeshOrderDlg.h" +#include "SMESHGUI_MeshOrderOp.h" #include "SMESHGUI_MeshUtils.h" -#include "SMESHGUI_Utils.h" #include "SMESHGUI_VTKUtils.h" -#include "SMESHGUI_HypothesesUtils.h" - -#include "SMDS_SetIterator.hxx" -#include - -#include "GEOMBase.h" -#include "GEOM_Actor.h" - -#include "LightApp_SelectionMgr.h" -#include "LightApp_UpdateFlags.h" -#include "SALOMEDSClient_SObject.hxx" -#include "SALOME_ListIO.hxx" -#include "SVTK_ViewWindow.h" -#include "SVTK_ViewModel.h" -#include "SalomeApp_Tools.h" -#include "SalomeApp_Application.h" -#include "SUIT_ResourceMgr.h" -#include "SUIT_OverrideCursor.h" -#include "SUIT_MessageBox.h" -#include "SUIT_Desktop.h" -#include "SUIT_Study.h" -#include "OB_Browser.h" - -// OCCT Includes +#include "SMESH_Actor.h" +#include "SMESH_ActorUtils.h" + +// SALOME GEOM includes +#include +#include +#include + +// SALOME GUI includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// SALOME KERNEL includes +#include +#include +#include +#include "utilities.h" + +#include CORBA_SERVER_HEADER(SMESH_Group) + +// OCCT includes +#include +#include #include +#include +#include #include #include +#include #include #include -#include -#include -#include -#include -#include - #include -// QT Includes -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// VTK includes #include +#include -// IDL Headers -#include -#include CORBA_SERVER_HEADER(SMESH_Gen) -#include CORBA_SERVER_HEADER(SMESH_Mesh) - +// STL includes #include #include +#if !defined WIN32 && !defined __APPLE__ +#include +#endif -#define SPACING 5 -#define MARGIN 10 +#define SPACING 6 +#define MARGIN 11 #define COLONIZE(str) (QString(str).contains(":") > 0 ? QString(str) : QString(str) + " :" ) +#define __SHAPE_RGB__ 250, 0, 250 -#define _SEPARATOR(father) \ -{\ - /*new QLabel(father); new QLabel(father); new QLabel(father)*/;\ - (new QFrame(father))->setFrameStyle(QFrame::HLine | QFrame::Sunken);\ - (new QFrame(father))->setFrameStyle(QFrame::HLine | QFrame::Sunken);\ - (new QFrame(father))->setFrameStyle(QFrame::HLine | QFrame::Sunken);\ - (new QFrame(father))->setFrameStyle(QFrame::HLine | QFrame::Sunken);\ -} - -enum TCol { COL_ALGO = 0, COL_SHAPE, COL_ERROR, COL_SHAPEID, COL_PUBLISHED, NB_COLUMNS }; +enum TCol { + COL_ALGO = 0, COL_SHAPE, COL_ERROR, COL_SHAPEID, COL_PUBLISHED, COL_BAD_MESH, NB_COLUMNS +}; -using namespace SMESH; +//using namespace SMESH; -namespace SMESH { - +namespace SMESH +{ //============================================================================= /*! * \brief Allocate some memory at construction and release it at destruction. @@ -125,7 +132,8 @@ namespace SMESH { { char* myBuf; MemoryReserve(): myBuf( new char[1024*1024*1] ){} // 1M - ~MemoryReserve() { delete [] myBuf; } + void release() { delete [] myBuf; myBuf = 0; } + ~MemoryReserve() { release(); } }; // ========================================================================================= @@ -142,10 +150,10 @@ namespace SMESH { { myProperty = vtkProperty::New(); myProperty->SetRepresentationToWireframe(); - myProperty->SetColor( 250, 0, 250 ); - myProperty->SetAmbientColor( 250, 0, 250 ); - myProperty->SetDiffuseColor( 250, 0, 250 ); - //myProperty->SetSpecularColor( 250, 0, 250 ); + myProperty->SetColor( __SHAPE_RGB__ ); + myProperty->SetAmbientColor( __SHAPE_RGB__ ); + myProperty->SetDiffuseColor( __SHAPE_RGB__ ); + //myProperty->SetSpecularColor( __SHAPE_RGB__ ); myProperty->SetLineWidth( 5 ); } // ----------------------------------------------------------------------- @@ -182,7 +190,7 @@ namespace SMESH { // ----------------------------------------------------------------------- bool HasReadyActorsFor (int subShapeID, GEOM::GEOM_Object_var aMainShape ) { - string mainEntry; + std::string mainEntry; if ( !aMainShape->_is_nil() ) mainEntry = aMainShape->GetStudyEntry(); return ( myMainEntry == mainEntry && @@ -192,7 +200,8 @@ namespace SMESH { void Show( int subShapeID, GEOM::GEOM_Object_var aMainShape, bool only = false) { SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() ); - string mainEntry; + SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() ); + std::string mainEntry; if ( !aMainShape->_is_nil() ) mainEntry = aMainShape->GetStudyEntry(); if ( myMainEntry != mainEntry || aViewWindow != myViewWindow ) { // remove actors @@ -220,8 +229,13 @@ namespace SMESH { TopAbs_ShapeEnum type( aShape.ShapeType() >= TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE ); for ( TopExp_Explorer exp( aShape, type ); exp.More(); exp.Next() ) { //checkTriangulation( exp.Current() ); - if ( GEOM_Actor* anActor = getActor( exp.Current() )) + if ( GEOM_Actor* anActor = getActor( exp.Current() ) ) { + int UNbIsos = resMgr->integerValue( "Geometry", "iso_number_u", 1); + int VNbIsos = resMgr->integerValue( "Geometry", "iso_number_v", 1); + int aNbIsos[2] = { UNbIsos ? UNbIsos : 1, VNbIsos ? VNbIsos : 1 }; + anActor->SetNbIsos( aNbIsos ); myShownActors.push_back( anActor ); + } } if ( type == TopAbs_FACE ) { for ( TopExp_Explorer exp( aShape, TopAbs_EDGE ); exp.More(); exp.Next() ) { @@ -243,7 +257,7 @@ namespace SMESH { TActorVec myActors; TActorVec myShownActors; TopTools_IndexedMapOfShape myIndexToShape; - string myMainEntry; + std::string myMainEntry; SVTK_ViewWindow* myViewWindow; vtkProperty* myProperty; std::set myBuiltSubs; @@ -260,20 +274,25 @@ namespace SMESH { GEOM_Actor* getActor(const TopoDS_Shape& shape) { int index = myIndexToShape.FindIndex( shape ) - 1; - if ( index < 0 || index >= myActors.size() ) + if ( index < 0 || index >= (int) myActors.size() ) return 0; GEOM_Actor* & actor = myActors[ index ]; if ( !actor ) { actor = GEOM_Actor::New(); if ( actor ) { - actor->setInputShape(shape,0,0); - //actor->SetProperty(myProperty); - actor->SetShadingProperty(myProperty); - actor->SetWireframeProperty(myProperty); - actor->SetPreviewProperty(myProperty); + actor->SetShape(shape,0,0); + // actor->SetProperty(myProperty); + // actor->SetShadingProperty(myProperty); + // actor->SetWireframeProperty(myProperty); + // actor->SetPreviewProperty(myProperty); actor->PickableOff(); - // if ( shape.ShapeType() == TopAbs_EDGE ) - // actor->SubShapeOn(); + // + actor->SetWidth( myProperty->GetLineWidth() ); + actor->SetIsosWidth( myProperty->GetLineWidth() ); + actor->SetIsosColor( __SHAPE_RGB__ ); + actor->SetColor( __SHAPE_RGB__ ); + // if ( shape.ShapeType() == TopAbs_EDGE ) + // actor->SubShapeOn(); myViewWindow->AddActor( actor ); } } @@ -286,7 +305,7 @@ namespace SMESH { Standard_Boolean alreadymesh = Standard_True; TopExp_Explorer ex(shape, TopAbs_FACE); if ( ex.More() ) - for (; ex.More(); ex.Next()) { + for ( ; ex.More(); ex.Next()) { const TopoDS_Face& aFace = TopoDS::Face(ex.Current()); Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc); if(aPoly.IsNull()) { alreadymesh = Standard_False; break; } @@ -303,7 +322,7 @@ namespace SMESH { BRepBndLib::Add(shape, B); Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); - double deflection = Max( aXmax-aXmin , Max ( aYmax-aYmin , aZmax-aZmin)) * 0.01 *4; + double deflection = Max( aXmax-aXmin, Max ( aYmax-aYmin, aZmax-aZmin)) * 0.01 *4; BRepMesh_IncrementalMesh MESH(shape,deflection); } // ----------------------------------------------------------------------- @@ -327,18 +346,24 @@ namespace SMESH { { QString text; switch ( errCode ) { - CASE2TEXT( COMPERR_OK ); - CASE2TEXT( COMPERR_BAD_INPUT_MESH); - CASE2TEXT( COMPERR_STD_EXCEPTION ); - CASE2TEXT( COMPERR_OCC_EXCEPTION ); + CASE2TEXT( COMPERR_OK ); + CASE2TEXT( COMPERR_BAD_INPUT_MESH ); + CASE2TEXT( COMPERR_STD_EXCEPTION ); + CASE2TEXT( COMPERR_OCC_EXCEPTION ); case SMESH::COMPERR_SLM_EXCEPTION: break; // avoid double "Salome exception" - CASE2TEXT( COMPERR_EXCEPTION ); - CASE2TEXT( COMPERR_MEMORY_PB ); - CASE2TEXT( COMPERR_BAD_SHAPE ); + CASE2TEXT( COMPERR_EXCEPTION ); + CASE2TEXT( COMPERR_MEMORY_PB ); + CASE2TEXT( COMPERR_BAD_SHAPE ); + CASE2TEXT( COMPERR_CANCELED ); + CASE2TEXT( COMPERR_NO_MESH_ON_SHAPE ); + CASE2TEXT( COMPERR_BAD_PARMETERS ); case SMESH::COMPERR_ALGO_FAILED: if ( strlen(comment) == 0 ) text = QObject::tr("COMPERR_ALGO_FAILED"); break; + case SMESH::COMPERR_WARNING: + text = QObject::tr( (comment && strlen(comment)) ? "COMPERR_WARNING" : "COMPERR_UNKNOWN"); + break; default: text = QString("#%1").arg( -errCode ); } @@ -347,7 +372,7 @@ namespace SMESH { } // ----------------------------------------------------------------------- /*! - * \brief Return SO of a subshape + * \brief Return SO of a sub-shape */ _PTR(SObject) getSubShapeSO( int subShapeID, GEOM::GEOM_Object_var aMainShape) { @@ -364,7 +389,11 @@ namespace SMESH { if ( !geom->_is_nil() ) { GEOM::ListOfLong_var list = geom->GetSubShapeIndices(); if ( list->length() == 1 && list[0] == subShapeID ) - subSO = it->Value(); + { + GEOM::GEOM_Object_var mainGO = geom->GetMainShape(); + if ( aMainShape->IsSame( mainGO )) + subSO = it->Value(); + } } } } @@ -372,17 +401,23 @@ namespace SMESH { } // ----------------------------------------------------------------------- /*! - * \brief Return subshape by ID + * \brief Return sub-shape by ID. WARNING: UnRegister() must be called on a result */ GEOM::GEOM_Object_ptr getSubShape( int subShapeID, GEOM::GEOM_Object_var aMainShape) { GEOM::GEOM_Object_var aSubShape; - if ( subShapeID == 1 ) + if ( subShapeID == 1 ) { aSubShape = aMainShape; - else if ( _PTR(SObject) so = getSubShapeSO( subShapeID, aMainShape )) + aSubShape->Register(); + } + else if ( _PTR(SObject) so = getSubShapeSO( subShapeID, aMainShape )) { aSubShape = SMESH::SObjectToInterface( so ); - else + aSubShape->Register(); + } + else { aSubShape = SMESH::GetSubShape( aMainShape, subShapeID ); + // future call of UnRegister() will delete a servant of this new object + } return aSubShape._retn(); } // ----------------------------------------------------------------------- @@ -410,16 +445,19 @@ namespace SMESH { } // ----------------------------------------------------------------------- /*! - * \brief Return text describing a subshape + * \brief Return text describing a sub-shape */ QString shapeText(int subShapeID, GEOM::GEOM_Object_var aMainShape ) { QString text; - if ( _PTR(SObject) aSO = getSubShapeSO( subShapeID, aMainShape )) - text = aSO->GetName(); + if ( _PTR(SObject) aSO = getSubShapeSO( subShapeID, aMainShape )) { + text = aSO->GetName().c_str(); + text += QString(" (%1)").arg( aSO->GetID().c_str() ); + } else { text = QString("#%1").arg( subShapeID ); - QString typeName = shapeTypeName( getSubShape( subShapeID, aMainShape )); + GEOM::GEOM_Object_wrap shape = getSubShape( subShapeID, aMainShape ); + QString typeName = shapeTypeName( shape ); if ( typeName.length() ) text += QString(" (%1)").arg(typeName); } @@ -429,21 +467,22 @@ namespace SMESH { /*! * \brief Return a list of selected rows */ - bool getSelectedRows(QTable* table, list< int > & rows) + int getSelectedRows(QTableWidget* table, QList& rows) { rows.clear(); - int nbSel = table->numSelections(); - for ( int i = 0; i < nbSel; ++i ) + QList selRanges = table->selectedRanges(); + QTableWidgetSelectionRange range; + foreach( range, selRanges ) { - QTableSelection selected = table->selection(i); - if ( !selected.isActive() ) continue; - for ( int row = selected.topRow(); row <= selected.bottomRow(); ++row ) - rows.push_back( row ); + for ( int row = range.topRow(); row <= range.bottomRow(); ++row ) + if ( !rows.count( row )) + rows.append( row ); } - if (rows.empty() && table->currentRow() > -1 ) - rows.push_back( table->currentRow() ); + if ( rows.isEmpty() && table->currentRow() > -1 ) + if ( !rows.count( table->currentRow() )) + rows.append( table->currentRow() ); - return !rows.empty(); + return rows.count(); } } // namespace SMESH @@ -451,214 +490,32 @@ namespace SMESH { // ========================================================================================= /*! - * \brief Box showing mesh info + * \brief Dialog to compute a mesh and show computation errors */ -// ========================================================================================= +//======================================================================= -SMESHGUI_MeshInfosBox::SMESHGUI_MeshInfosBox(const bool full, QWidget* theParent) - :QGroupBox( 4, Qt::Horizontal, tr("SMESH_MESHINFO_TITLE"), theParent ), myFull( full ) +SMESHGUI_ComputeDlg::SMESHGUI_ComputeDlg( QWidget* parent, bool ForEval ) + : SMESHGUI_Dialog( parent, false, true, Close | Help ) { - // title - QLabel* lab1 = new QLabel(this); - QLabel* lab2 = new QLabel(tr("SMESH_MESHINFO_ORDER0"), this ); - QLabel* lab3 = new QLabel(tr("SMESH_MESHINFO_ORDER1"), this ); - QLabel* lab4 = new QLabel(tr("SMESH_MESHINFO_ORDER2"), this ); - - QFont italic = lab1->font(); italic.setItalic(true); - QFont bold = lab1->font(); bold.setBold(true); + QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame()); + aDlgLay->setMargin( 0 ); + aDlgLay->setSpacing( SPACING ); - lab1->setMinimumWidth(100); lab1->setFont( italic ); - lab2->setMinimumWidth(100); lab2->setFont( italic ); - lab3->setMinimumWidth(100); lab3->setFont( italic ); - lab4->setMinimumWidth(100); lab4->setFont( italic ); + QFrame* aMainFrame = createMainFrame(mainFrame(),ForEval); - if ( myFull ) - { - // nodes - (new QLabel(COLONIZE(tr("SMESH_MESHINFO_NODES")), this ))->setFont( bold ); - myNbNode = new QLabel( this ); - new QLabel(this); - new QLabel(this); - - _SEPARATOR(this); - - // edges - (new QLabel(COLONIZE(tr("SMESH_MESHINFO_EDGES")), this ))->setFont( bold ); - myNbEdge = new QLabel( this ); - myNbLinEdge = new QLabel( this ); - myNbQuadEdge = new QLabel( this ); - - _SEPARATOR(this); - - // faces - (new QLabel(COLONIZE(tr("SMESH_MESHINFO_FACES")), this))->setFont( bold ); - myNbFace = new QLabel( this ); - myNbLinFace = new QLabel( this ); - myNbQuadFace = new QLabel( this ); - // triangles - new QLabel(COLONIZE(tr("SMESH_MESHINFO_TRIANGLES")), this ); - myNbTrai = new QLabel( this ); - myNbLinTrai = new QLabel( this ); - myNbQuadTrai = new QLabel( this ); - // quadrangles - new QLabel(COLONIZE(tr("SMESH_MESHINFO_QUADRANGLES")), this ); - myNbQuad = new QLabel( this ); - myNbLinQuad = new QLabel( this ); - myNbQuadQuad = new QLabel( this ); - // poligones - new QLabel(COLONIZE(tr("SMESH_MESHINFO_POLYGONES")), this ); - myNbPolyg = new QLabel( this ); - new QLabel("",this ); - new QLabel("", this ); - - _SEPARATOR(this); - - // volumes - (new QLabel(COLONIZE(tr("SMESH_MESHINFO_VOLUMES")), this))->setFont( bold ); - myNbVolum = new QLabel( this ); - myNbLinVolum = new QLabel( this ); - myNbQuadVolum = new QLabel( this ); - // tetras - new QLabel(COLONIZE(tr("SMESH_MESHINFO_TETRAS")), this ); - myNbTetra = new QLabel( this ); - myNbLinTetra = new QLabel( this ); - myNbQuadTetra = new QLabel( this ); - // hexas - new QLabel(COLONIZE(tr("SMESH_MESHINFO_HEXAS")), this ); - myNbHexa = new QLabel( this ); - myNbLinHexa = new QLabel( this ); - myNbQuadHexa = new QLabel( this ); - // pyras - new QLabel(COLONIZE(tr("SMESH_MESHINFO_PYRAS")), this ); - myNbPyra = new QLabel( this ); - myNbLinPyra = new QLabel( this ); - myNbQuadPyra = new QLabel( this ); - // prisms - new QLabel(COLONIZE(tr("SMESH_MESHINFO_PRISMS")), this ); - myNbPrism = new QLabel( this ); - myNbLinPrism = new QLabel( this ); - myNbQuadPrism = new QLabel( this ); - // polyedres - new QLabel(COLONIZE(tr("SMESH_MESHINFO_POLYEDRES")), this ); - myNbPolyh = new QLabel( this ); - new QLabel("", this ); - new QLabel("", this ); - } - else - { - // nodes - new QLabel(COLONIZE(tr("SMESH_MESHINFO_NODES")), this ); - myNbNode = new QLabel( this ); - new QLabel(this); - new QLabel(this); - - // edges - new QLabel(COLONIZE(tr("SMESH_MESHINFO_EDGES")), this ); - myNbEdge = new QLabel( this ); - myNbLinEdge = new QLabel( this ); - myNbQuadEdge = new QLabel( this ); - - // faces - new QLabel(COLONIZE(tr("SMESH_MESHINFO_FACES")), this); - myNbFace = new QLabel( this ); - myNbLinFace = new QLabel( this ); - myNbQuadFace = new QLabel( this ); - - // volumes - new QLabel(COLONIZE(tr("SMESH_MESHINFO_VOLUMES")), this); - myNbVolum = new QLabel( this ); - myNbLinVolum = new QLabel( this ); - myNbQuadVolum = new QLabel( this ); - } -} - -// ========================================================================================= -/*! - * \brief Set mesh info - */ -// ========================================================================================= + aDlgLay->addWidget(aMainFrame); -void SMESHGUI_MeshInfosBox::SetInfoByMesh(SMESH::SMESH_Mesh_var mesh) -{ - const SMESH::ElementOrder lin = SMESH::ORDER_LINEAR; - int nbTot, nbLin; - - // nodes - myNbNode ->setText( QString("%1").arg( mesh->NbNodes() )); - - // edges - nbTot = mesh->NbEdges(), nbLin = mesh->NbEdgesOfOrder(lin); - myNbEdge ->setText( QString("%1").arg( nbTot )); - myNbLinEdge ->setText( QString("%1").arg( nbLin )); - myNbQuadEdge ->setText( QString("%1").arg( nbTot - nbLin )); - - // faces - nbTot = mesh->NbFaces(), nbLin = mesh->NbFacesOfOrder(lin); - myNbFace ->setText( QString("%1").arg( nbTot )); - myNbLinFace ->setText( QString("%1").arg( nbLin )); - myNbQuadFace ->setText( QString("%1").arg( nbTot - nbLin )); - - // volumes - nbTot = mesh->NbVolumes(), nbLin = mesh->NbVolumesOfOrder(lin); - myNbVolum ->setText( QString("%1").arg( nbTot )); - myNbLinVolum ->setText( QString("%1").arg( nbLin )); - myNbQuadVolum->setText( QString("%1").arg( nbTot - nbLin )); - - if ( myFull ) - { - // triangles - nbTot = mesh->NbTriangles(), nbLin = mesh->NbTrianglesOfOrder(lin); - myNbTrai ->setText( QString("%1").arg( nbTot )); - myNbLinTrai ->setText( QString("%1").arg( nbLin )); - myNbQuadTrai ->setText( QString("%1").arg( nbTot - nbLin )); - // quadrangles - nbTot = mesh->NbQuadrangles(), nbLin = mesh->NbQuadranglesOfOrder(lin); - myNbQuad ->setText( QString("%1").arg( nbTot )); - myNbLinQuad ->setText( QString("%1").arg( nbLin )); - myNbQuadQuad ->setText( QString("%1").arg( nbTot - nbLin )); - // poligones - myNbPolyg ->setText( QString("%1").arg( mesh->NbPolygons() )); - - // tetras - nbTot = mesh->NbTetras(), nbLin = mesh->NbTetrasOfOrder(lin); - myNbTetra ->setText( QString("%1").arg( nbTot )); - myNbLinTetra ->setText( QString("%1").arg( nbLin )); - myNbQuadTetra->setText( QString("%1").arg( nbTot - nbLin )); - // hexas - nbTot = mesh->NbHexas(), nbLin = mesh->NbHexasOfOrder(lin); - myNbHexa ->setText( QString("%1").arg( nbTot )); - myNbLinHexa ->setText( QString("%1").arg( nbLin )); - myNbQuadHexa ->setText( QString("%1").arg( nbTot - nbLin )); - // pyras - nbTot = mesh->NbPyramids(), nbLin = mesh->NbPyramidsOfOrder(lin); - myNbPyra ->setText( QString("%1").arg( nbTot )); - myNbLinPyra ->setText( QString("%1").arg( nbLin )); - myNbQuadPyra ->setText( QString("%1").arg( nbTot - nbLin )); - // prisms - nbTot = mesh->NbPrisms(), nbLin = mesh->NbPrismsOfOrder(lin); - myNbPrism ->setText( QString("%1").arg( nbTot )); - myNbLinPrism ->setText( QString("%1").arg( nbLin )); - myNbQuadPrism->setText( QString("%1").arg( nbTot - nbLin )); - // polyedres - myNbPolyh ->setText( QString("%1").arg( mesh->NbPolyhedrons() )); - } + aDlgLay->setStretchFactor(aMainFrame, 1); } // ========================================================================================= /*! - * \brief Dialog to compute a mesh and show computation errors + * \brief Destructor */ //======================================================================= -SMESHGUI_ComputeDlg::SMESHGUI_ComputeDlg(): SMESHGUI_Dialog( 0, false, true, OK/* | Help*/ ) +SMESHGUI_ComputeDlg::~SMESHGUI_ComputeDlg() { - QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame(), 0, SPACING); - - QFrame* aMainFrame = createMainFrame (mainFrame()); - - aDlgLay->addWidget(aMainFrame); - - aDlgLay->setStretchFactor(aMainFrame, 1); } //======================================================================= @@ -666,9 +523,7 @@ SMESHGUI_ComputeDlg::SMESHGUI_ComputeDlg(): SMESHGUI_Dialog( 0, false, true, OK/ // purpose : Create frame containing dialog's fields //======================================================================= -#define CASE2HEADER(enum) case enum: header = QObject::tr( #enum "_HEADER" ); break; - -QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent) +QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent, bool ForEval) { QFrame* aFrame = new QFrame(theParent); @@ -677,16 +532,30 @@ QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent) // constructor - QButtonGroup* aPixGrp = new QButtonGroup(1, Qt::Vertical, tr("CONSTRUCTOR"), aFrame); - aPixGrp->setExclusive(TRUE); + QGroupBox* aPixGrp; + if(ForEval) { + aPixGrp = new QGroupBox(tr("EVAL_DLG"), aFrame); + } + else { + aPixGrp = new QGroupBox(tr("CONSTRUCTOR"), aFrame); + } + QButtonGroup* aBtnGrp = new QButtonGroup(this); + QHBoxLayout* aPixGrpLayout = new QHBoxLayout(aPixGrp); + aPixGrpLayout->setMargin(MARGIN); aPixGrpLayout->setSpacing(SPACING); + QRadioButton* aRBut = new QRadioButton(aPixGrp); - aRBut->setPixmap(iconCompute); - aRBut->setChecked(TRUE); + aRBut->setIcon(iconCompute); + aRBut->setChecked(true); + aPixGrpLayout->addWidget(aRBut); + aBtnGrp->addButton(aRBut, 0); // Mesh name - QHGroupBox* nameBox = new QHGroupBox(tr("SMESH_MESHINFO_NAME"), aFrame ); + QGroupBox* nameBox = new QGroupBox(tr("SMESH_MESHINFO_NAME"), aFrame ); + QHBoxLayout* nameBoxLayout = new QHBoxLayout(nameBox); + nameBoxLayout->setMargin(MARGIN); nameBoxLayout->setSpacing(SPACING); myMeshName = new QLabel(nameBox); + nameBoxLayout->addWidget(myMeshName); // Mesh Info @@ -695,54 +564,74 @@ QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent) // Computation errors - myCompErrorGroup = new QGroupBox(tr("ERRORS"), aFrame, "myCompErrorGroup"); - myTable = new QTable( 1, NB_COLUMNS, myCompErrorGroup, "myTable"); - myShowBtn = new QPushButton(tr("SHOW_SHAPE"), myCompErrorGroup, "myShowBtn"); - myPublishBtn = new QPushButton(tr("PUBLISH_SHAPE"), myCompErrorGroup, "myPublishBtn"); + myCompErrorGroup = new QGroupBox(tr("ERRORS"), aFrame); + myWarningLabel = new QLabel(QString("%1").arg(tr("COMPUTE_WARNING")), myCompErrorGroup); + myTable = new QTableWidget( 1, NB_COLUMNS, myCompErrorGroup); + myShowBtn = new QPushButton(tr("SHOW_SHAPE"), myCompErrorGroup); + myPublishBtn = new QPushButton(tr("PUBLISH_SHAPE"), myCompErrorGroup); + myBadMeshBtn = new QPushButton(tr("SHOW_BAD_MESH"), myCompErrorGroup); + myBadMeshToGroupBtn = new QPushButton(tr("GROUP_OF_BAD_MESH"), myCompErrorGroup); - myTable->setReadOnly( TRUE ); + //myTable->setReadOnly( true ); // VSR: check + myTable->setEditTriggers( QAbstractItemView::NoEditTriggers ); myTable->hideColumn( COL_PUBLISHED ); myTable->hideColumn( COL_SHAPEID ); - myTable->setColumnStretchable( COL_ERROR, 1 ); - for ( int col = 0; col < NB_COLUMNS; ++col ) { - QString header; - switch ( col ) { - CASE2HEADER( COL_ALGO ); - CASE2HEADER( COL_SHAPE ); - CASE2HEADER( COL_ERROR ); - CASE2HEADER( COL_SHAPEID ); - CASE2HEADER( COL_PUBLISHED); - } - myTable->horizontalHeader()->setLabel( col, header ); - } + myTable->hideColumn( COL_BAD_MESH ); +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + myTable->horizontalHeader()->setResizeMode( COL_ERROR, QHeaderView::Interactive ); +#else + myTable->horizontalHeader()->setSectionResizeMode( COL_ERROR, QHeaderView::Interactive ); +#endif + myTable->setWordWrap( true ); + myTable->horizontalHeader()->setStretchLastSection( true ); + myTable->setMinimumWidth( 500 ); + + QStringList headers; + headers << tr( "COL_ALGO_HEADER" ); + headers << tr( "COL_SHAPE_HEADER" ); + headers << tr( "COL_ERROR_HEADER" ); + headers << tr( "COL_SHAPEID_HEADER" ); + headers << tr( "COL_PUBLISHED_HEADER" ); + + myTable->setHorizontalHeaderLabels( headers ); + // layouting - myCompErrorGroup->setColumnLayout(0, Qt::Vertical); - myCompErrorGroup->layout()->setSpacing(0); - myCompErrorGroup->layout()->setMargin(0); - QGridLayout* grpLayout = new QGridLayout(myCompErrorGroup->layout()); - grpLayout->setAlignment(Qt::AlignTop); + QGridLayout* grpLayout = new QGridLayout(myCompErrorGroup); grpLayout->setSpacing(SPACING); grpLayout->setMargin(MARGIN); - grpLayout->addMultiCellWidget( myTable, 0, 2, 0, 0 ); - grpLayout->addWidget ( myShowBtn, 0, 1 ); - grpLayout->addWidget ( myPublishBtn, 1, 1 ); - grpLayout->setRowStretch( 2, 1 ); + grpLayout->addWidget( myWarningLabel, 0, 0, 1, 4 ); + grpLayout->addWidget( myTable, 1, 0, 1, 4 ); + grpLayout->addWidget( myShowBtn, 2, 0 ); + grpLayout->addWidget( myPublishBtn, 2, 1 ); + grpLayout->addWidget( myBadMeshBtn, 2, 2 ); + grpLayout->addWidget( myBadMeshToGroupBtn, 2, 3 ); + grpLayout->setColumnStretch( 3, 1 ); // Hypothesis definition errors - myHypErrorGroup = new QGroupBox(1,Qt::Vertical, tr("SMESH_WRN_MISSING_PARAMETERS"),aFrame); + myHypErrorGroup = new QGroupBox(tr("SMESH_WRN_MISSING_PARAMETERS"), aFrame); + QHBoxLayout* myHypErrorGroupLayout = new QHBoxLayout(myHypErrorGroup); + myHypErrorGroupLayout->setMargin(MARGIN); + myHypErrorGroupLayout->setSpacing(SPACING); myHypErrorLabel = new QLabel(myHypErrorGroup); + myHypErrorGroupLayout->addWidget(myHypErrorLabel); // Memory Lack Label - myMemoryLackGroup = new QVGroupBox(tr("ERRORS"), aFrame, "memlackGrBox"); + myMemoryLackGroup = new QGroupBox(tr("ERRORS"), aFrame); + QVBoxLayout* myMemoryLackGroupLayout = new QVBoxLayout(myMemoryLackGroup); + myMemoryLackGroupLayout->setMargin(MARGIN); + myMemoryLackGroupLayout->setSpacing(SPACING); QLabel* memLackLabel = new QLabel(tr("MEMORY_LACK"), myMemoryLackGroup); QFont bold = memLackLabel->font(); bold.setBold(true); memLackLabel->setFont( bold ); memLackLabel->setMinimumWidth(300); + myMemoryLackGroupLayout->addWidget(memLackLabel); // add all widgets to aFrame QVBoxLayout* aLay = new QVBoxLayout(aFrame); + aLay->setMargin( MARGIN ); + aLay->setSpacing( SPACING ); aLay->addWidget( aPixGrp ); aLay->addWidget( nameBox ); aLay->addWidget( myBriefInfo ); @@ -763,217 +652,590 @@ QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent) */ //================================================================================ -SMESHGUI_ComputeOp::SMESHGUI_ComputeOp() +SMESHGUI_BaseComputeOp::SMESHGUI_BaseComputeOp() + : SMESHGUI_Operation(), myCompDlg( 0 ) { - myDlg = new SMESHGUI_ComputeDlg; - myTShapeDisplayer = new TShapeDisplayer(); + myTShapeDisplayer = new SMESH::TShapeDisplayer(); + myBadMeshDisplayer = 0; + //myHelpFileName = "/files/about_meshes.htm"; // V3 myHelpFileName = "about_meshes_page.html"; // V4 +} - // connect signals and slots - connect(myDlg->myShowBtn, SIGNAL (clicked()), SLOT(onPreviewShape())); - connect(myDlg->myPublishBtn, SIGNAL (clicked()), SLOT(onPublishShape())); - connect(table(),SIGNAL(selectionChanged()), SLOT(currentCellChanged())); - connect(table(),SIGNAL(currentChanged(int,int)), SLOT(currentCellChanged())); +SMESH::SMESH_Mesh_ptr SMESHGUI_BaseComputeOp::getMesh() +{ + LightApp_SelectionMgr* Sel = selectionMgr(); + SALOME_ListIO selected; Sel->selectedObjects( selected ); + Handle(SALOME_InteractiveObject) anIO = selected.First(); + SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(anIO); + return myMesh->_is_nil() ? aMesh._retn() : SMESH::SMESH_Mesh::_duplicate( myMesh ); } -//======================================================================= -// function : startOperation() -// purpose : Init dialog fields, connect signals and slots, show dialog -//======================================================================= +//================================================================================ +/*! + * \brief Start operation + * \purpose Init dialog fields, connect signals and slots, show dialog + */ +//================================================================================ -void SMESHGUI_ComputeOp::startOperation() +void SMESHGUI_BaseComputeOp::startOperation() { - SMESHGUI_Operation::startOperation(); - - // check selection + // create compute dialog if not created before + computeDlg(); - SMESH::SMESH_Mesh_var aMesh; + myMesh = SMESH::SMESH_Mesh::_nil(); myMainShape = GEOM::GEOM_Object::_nil(); + myCurShape = GEOM::GEOM_Object::_nil(); + // check selection LightApp_SelectionMgr *Sel = selectionMgr(); SALOME_ListIO selected; Sel->selectedObjects( selected ); int nbSel = selected.Extent(); if (nbSel != 1) { - SUIT_MessageBox::warn1(desktop(), - tr("SMESH_WRN_WARNING"), - tr("SMESH_WRN_NO_AVAILABLE_DATA"), - tr("SMESH_BUT_OK")); + SUIT_MessageBox::warning(desktop(), + tr("SMESH_WRN_WARNING"), + tr("SMESH_WRN_NO_AVAILABLE_DATA")); onCancel(); return; } - Handle(SALOME_InteractiveObject) IObject = selected.First(); - aMesh = SMESH::GetMeshByIO(IObject); - if (aMesh->_is_nil()) { - SUIT_MessageBox::warn1(desktop(), - tr("SMESH_WRN_WARNING"), - tr("SMESH_WRN_NO_AVAILABLE_DATA"), - tr("SMESH_BUT_OK")); + myIObject = selected.First(); + CORBA::Object_var anObj = SMESH::IObjectToObject( myIObject ); + + myMesh = SMESH::SMESH_Mesh::_narrow(anObj); + if ( myMesh->_is_nil() ) + { + SMESH::SMESH_subMesh_var aSubMesh = SMESH::SMESH_subMesh::_narrow(anObj); + if ( !aSubMesh->_is_nil() ) + { + myMesh = aSubMesh->GetFather(); + myCurShape = aSubMesh->GetSubShape(); + } + } + else + { + myCurShape = myMesh->GetShapeToMesh(); + } + + if (myMesh->_is_nil()) { + SUIT_MessageBox::warning(desktop(), + tr("SMESH_WRN_WARNING"), + tr("SMESH_WRN_NO_AVAILABLE_DATA")); onCancel(); return; } + myMainShape = myMesh->GetShapeToMesh(); + + SMESHGUI_Operation::startOperation(); +} + +//================================================================================ +//================================================================================ + +SMESHGUI_ComputeDlg_QThread::SMESHGUI_ComputeDlg_QThread(SMESH::SMESH_Gen_var gen, + SMESH::SMESH_Mesh_var mesh, + GEOM::GEOM_Object_var mainShape) +{ + myResult = false; + myGen = gen; + myMesh = mesh; + myMainShape = mainShape; +} + +void SMESHGUI_ComputeDlg_QThread::run() +{ + myResult = myGen->Compute(myMesh, myMainShape); +} + +bool SMESHGUI_ComputeDlg_QThread::result() +{ + return myResult; +} + +void SMESHGUI_ComputeDlg_QThread::cancel() +{ + myGen->CancelCompute(myMesh, myMainShape); +} + +//================================================================================ +//================================================================================ + +SMESHGUI_ComputeDlg_QThreadQDialog:: +SMESHGUI_ComputeDlg_QThreadQDialog(QWidget * parent, + SMESH::SMESH_Gen_var gen, + SMESH::SMESH_Mesh_var mesh, + GEOM::GEOM_Object_var mainShape) + : QDialog(parent, + Qt::WindowSystemMenuHint | + Qt::WindowCloseButtonHint | + Qt::Dialog | + Qt::WindowMaximizeButtonHint), + qthread(gen, mesh, mainShape) +{ + // -- + setWindowTitle(tr("TITLE")); + setMinimumWidth( 200 ); + + cancelButton = new QPushButton(tr("CANCEL")); + cancelButton->setDefault(true); + cancelButton->setCheckable(true); + + QLabel * nbNodesName = new QLabel(tr("SMESH_MESHINFO_NODES"), this ); + QLabel * nbElemsName = new QLabel(tr("SMESH_MESHINFO_ELEMENTS"), this ); + nbNodesLabel = new QLabel("0", this ); + nbElemsLabel = new QLabel("0", this ); +#if !defined WIN32 && !defined __APPLE__ + QLabel * freeRAMName = new QLabel(tr("SMESH_FREERAM"), this ); + freeRAMLabel = new QLabel("", this ); +#endif + progressBar = new QProgressBar(this); + progressBar->setMinimum( 0 ); + progressBar->setMaximum( 1000 ); + + QGridLayout* layout = new QGridLayout(this); + layout->setMargin( MARGIN ); + layout->setSpacing( SPACING ); + int row = 0; + layout->addWidget(nbNodesName, row, 0); + layout->addWidget(nbNodesLabel, row++, 1); + layout->addWidget(nbElemsName, row, 0); + layout->addWidget(nbElemsLabel, row++, 1); +#if !defined WIN32 && !defined __APPLE__ + layout->addWidget(freeRAMName, row, 0); + layout->addWidget(freeRAMLabel, row++, 1); +#endif + layout->addWidget(progressBar, row++, 0, 1, 2); + layout->addWidget(cancelButton, row++, 0, 1, 2); + adjustSize(); + update(); + + connect(cancelButton, SIGNAL(clicked()), this, SLOT(onCancel())); + // -- + startTimer(300); // millisecs + qthread.start(); +} + +bool SMESHGUI_ComputeDlg_QThreadQDialog::result() +{ + return qthread.result(); +} + +void SMESHGUI_ComputeDlg_QThreadQDialog::onCancel() +{ + qthread.cancel(); + cancelButton->setText( tr("CANCELING")); + cancelButton->setEnabled(false); +} + +void SMESHGUI_ComputeDlg_QThreadQDialog::timerEvent(QTimerEvent *event) +{ + if ( !cancelButton->isChecked() ) // not yet cancelled + progressBar->setValue( progressBar->maximum() * qthread.getMesh()->GetComputeProgress() ); + + if(qthread.isFinished()) + { + close(); + } + else + { + nbNodesLabel->setText( QString("%1").arg( qthread.getMesh()->NbNodes() )); + nbElemsLabel->setText( QString("%1").arg( qthread.getMesh()->NbElements() )); +#if !defined WIN32 && !defined __APPLE__ + struct sysinfo si; + const int err = sysinfo( &si ); + if ( err ) + freeRAMLabel->setText(""); + else + freeRAMLabel->setText( tr("SMESH_GIGABYTE").arg + ( si.freeram * si.mem_unit /1024./1024./1024., 0, 'f', 2 )); +#endif + } + event->accept(); +} + +void SMESHGUI_ComputeDlg_QThreadQDialog::closeEvent(QCloseEvent *event) +{ + if(qthread.isRunning()) + { + event->ignore(); + return; + } + event->accept(); +} + +//================================================================================ +/*! + * \brief computeMesh() +*/ +//================================================================================ + +void SMESHGUI_BaseComputeOp::computeMesh() +{ // COMPUTE MESH - MemoryReserve aMemoryReserve; + SMESH::MemoryReserve aMemoryReserve; SMESH::compute_error_array_var aCompErrors; QString aHypErrors; bool computeFailed = true, memoryLack = false; - _PTR(SObject) aMeshSObj = SMESH::FindSObject(aMesh); - myMainShape = aMesh->GetShapeToMesh(); - bool hasShape = aMesh->HasShapeToMesh(); + _PTR(SObject) aMeshSObj = SMESH::FindSObject(myMesh); + if ( !aMeshSObj ) // IPAL 21340 + return; + bool hasShape = myMesh->HasShapeToMesh(); bool shapeOK = myMainShape->_is_nil() ? !hasShape : hasShape; - if ( shapeOK && aMeshSObj ) + if ( shapeOK ) { - myDlg->myMeshName->setText( aMeshSObj->GetName() ); + myCompDlg->myMeshName->setText( aMeshSObj->GetName().c_str() ); SMESH::SMESH_Gen_var gen = getSMESHGUI()->GetSMESHGen(); - SMESH::algo_error_array_var errors = gen->GetAlgoState(aMesh,myMainShape); + SMESH::algo_error_array_var errors = gen->GetAlgoState(myMesh,myMainShape); if ( errors->length() > 0 ) { aHypErrors = SMESH::GetMessageOnAlgoStateErrors( errors.in() ); } + if ( myMesh->HasModificationsToDiscard() && // issue 0020693 + SUIT_MessageBox::question( desktop(), tr( "SMESH_WARNING" ), + tr( "FULL_RECOMPUTE_QUESTION" ), + tr( "SMESH_BUT_YES" ), tr( "SMESH_BUT_NO" ), 1, 0 ) == 0 ) + myMesh->Clear(); SUIT_OverrideCursor aWaitCursor; try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 OCC_CATCH_SIGNALS; -#endif - if (gen->Compute(aMesh, myMainShape)) - computeFailed = false; + SMESHGUI_ComputeDlg_QThreadQDialog qthreaddialog(desktop(), gen, myMesh, myCurShape); + qthreaddialog.exec(); + computeFailed = !qthreaddialog.result(); } - catch(const SALOME::SALOME_Exception & S_ex){ + catch(const SALOME::SALOME_Exception & S_ex) { memoryLack = true; } try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 OCC_CATCH_SIGNALS; -#endif - aCompErrors = gen->GetComputeErrors( aMesh, myMainShape ); + aCompErrors = gen->GetComputeErrors( myMesh, myMainShape ); // check if there are memory problems - for ( int i = 0; (i < aCompErrors->length()) && !memoryLack; ++i ) + for ( CORBA::ULong i = 0; (i < aCompErrors->length()) && !memoryLack; ++i ) memoryLack = ( aCompErrors[ i ].code == SMESH::COMPERR_MEMORY_PB ); } - catch(const SALOME::SALOME_Exception & S_ex){ + catch(const SALOME::SALOME_Exception & S_ex) { + memoryLack = true; + } + + if ( !memoryLack && !SMDS_Mesh::CheckMemory(true) ) { // has memory to show dialog boxes? memoryLack = true; } // NPAL16631: if ( !memoryLack ) { - SMESH::ModifiedMesh(aMeshSObj, !computeFailed, aMesh->NbNodes() == 0); + _PTR(SObject) sobj = SMESH::GetActiveStudyDocument()->FindObjectID(myIObject->getEntry()); + SMESH::ModifiedMesh( sobj, + !computeFailed && aHypErrors.isEmpty(), + myMesh->NbNodes() == 0); update( UF_ObjBrowser | UF_Model ); // SHOW MESH // NPAL16631: if ( getSMESHGUI()->automaticUpdate() ) - if ( !memoryLack && getSMESHGUI()->automaticUpdate() ) + SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() ); + bool limitExceeded; + long limitSize = resMgr->integerValue( "SMESH", "update_limit", 500000 ); + int entities = SMESH_Actor::eAllEntity; + int hidden = 0; + long nbElements = 0; + if ( !memoryLack ) { - try { -#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 - OCC_CATCH_SIGNALS; -#endif - SMESH::Update(IObject, true); + // List of objects that will be updated automatically + typedef QList< QPair< SMESH::SMESH_IDSource_var, _PTR(SObject) > > TListOf_IDSrc_SObj; + TListOf_IDSrc_SObj aListToUpdate; + SMESH::SMESH_IDSource_var aMeshObj = + SMESH::SObjectToInterface( aMeshSObj ); + // put Mesh into list + aListToUpdate.append( TListOf_IDSrc_SObj::value_type( aMeshObj, aMeshSObj )); + SMESH::submesh_array_var aSubMeshes = myMesh->GetSubMeshes(); + // put SubMeshes into list + for ( CORBA::ULong i = 0; i < aSubMeshes->length(); i++ ) + { + SMESH::SMESH_subMesh_var sm = aSubMeshes[i]; + if ( CORBA::is_nil( sm ) ) continue; + _PTR(SObject) smSObj = SMESH::ObjectToSObject( sm ); + if ( !smSObj ) continue; + SMESH::SMESH_IDSource_var aSubMeshObj = + SMESH::SObjectToInterface( smSObj ); + SMESH_Actor *anActor = SMESH::FindActorByObject( aSubMeshObj ); + if ( anActor && anActor->GetVisibility() ) + aListToUpdate.append( TListOf_IDSrc_SObj::value_type( aSubMeshObj, smSObj )); + } + // put Groups into list + SMESH::ListOfGroups_var aGroups = myMesh->GetGroups(); + for ( size_t i = 0; i < aGroups->length(); ++i ) + { + SMESH::SMESH_GroupBase_var aGrp = aGroups[i]; + if ( CORBA::is_nil( aGrp ) ) continue; + SMESH::SMESH_Group_var aStdGroup = SMESH::SMESH_Group::_narrow( aGrp ); + if ( !aStdGroup->_is_nil() ) continue; // don't update standalone groups + _PTR(SObject) aGroupSO = SMESH::FindSObject( aGrp ); + if ( !aGroupSO ) continue; + SMESH::SMESH_IDSource_var aGroupObj = + SMESH::SObjectToInterface( aGroupSO ); + SMESH_Actor *anActor = SMESH::FindActorByObject( aGroupObj ); + if ( anActor && anActor->GetVisibility() ) + aListToUpdate.append( TListOf_IDSrc_SObj::value_type( aGroupObj, aGroupSO )); } - catch (...) { + + // update mesh, sub-mesh and groups, if it's possible + TListOf_IDSrc_SObj::iterator anIter; + for ( anIter = aListToUpdate.begin(); anIter != aListToUpdate.end(); anIter++ ) + { + SMESH::SMESH_Mesh_var aMesh = + SMESH::SMESH_Mesh::_narrow( SMESH::SObjectToObject( (*anIter).second )); + + if ( getSMESHGUI()->automaticUpdate( (*anIter).first, &entities, &limitExceeded, + &hidden, &nbElements ) ) + { + try { + OCC_CATCH_SIGNALS; + bool toDisplay = false; + if ( !aMesh->_is_nil() ) // display only a mesh + { + toDisplay = true; + SMESH_Actor *anActor = SMESH::FindActorByObject( aMesh ); + if ( !anActor ) anActor = SMESH::CreateActor( (*anIter).second->GetStudy(), + (*anIter).second->GetID().c_str(), + /*clearLog =*/ true ); + if ( anActor ) // actor is not created for an empty mesh + { + anActor->SetEntityMode( entities ); + SMESH::DisplayActor( SMESH::GetActiveWindow(), anActor ); + } + } + Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject + ( (*anIter).second->GetID().c_str(), "SMESH", (*anIter).second->GetName().c_str() ); + SMESH::Update(anIO, toDisplay); + if( SVTK_ViewWindow* vtkWnd = SMESH::GetVtkViewWindow(SMESH::GetActiveWindow() ) ) { + if( vtkWnd->getRenderer() ){ + vtkWnd->getRenderer()->ResetCameraClippingRange(); + } + } + + if ( limitExceeded && !aMesh->_is_nil() ) + { + QStringList hiddenMsg; + if ( hidden & SMESH_Actor::e0DElements ) hiddenMsg << tr( "SMESH_ELEMS0D" ); + if ( hidden & SMESH_Actor::eEdges ) hiddenMsg << tr( "SMESH_EDGES" ); + if ( hidden & SMESH_Actor::eFaces ) hiddenMsg << tr( "SMESH_FACES" ); + if ( hidden & SMESH_Actor::eVolumes ) hiddenMsg << tr( "SMESH_VOLUMES" ); + if ( hidden & SMESH_Actor::eBallElem ) hiddenMsg << tr( "SMESH_BALLS" ); + SUIT_MessageBox::warning( desktop(), + tr( "SMESH_WRN_WARNING" ), + tr( "SMESH_WRN_SIZE_INC_LIMIT_EXCEEDED" ). + arg( nbElements ). + arg( limitSize ). + arg( hiddenMsg.join(", "))); + } + } + catch (...) { #ifdef _DEBUG_ - cout << "Exception thrown during mesh visualization" << endl; + MESSAGE ( "Exception thrown during mesh visualization" ); #endif - if ( SMDS_Mesh::CheckMemory(true) ) { // has memory to show warning? - SMESH::OnVisuException(); + if ( SMDS_Mesh::CheckMemory(true) ) { // has memory to show warning? + SMESH::OnVisuException(); + } + else { + memoryLack = true; + } + } } - else { - memoryLack = true; + else if ( limitExceeded && !aMesh->_is_nil() ) + { + SUIT_MessageBox::warning( desktop(), + tr( "SMESH_WRN_WARNING" ), + tr( "SMESH_WRN_SIZE_LIMIT_EXCEEDED" ). + arg( nbElements ).arg( limitSize ) ); } } } - Sel->setSelectedObjects( selected ); + if ( LightApp_SelectionMgr *Sel = selectionMgr() ) + { + SALOME_ListIO selected; + selected.Append( myIObject ); + Sel->setSelectedObjects( selected ); + } } } - myDlg->setCaption(tr( computeFailed ? "SMESH_WRN_COMPUTE_FAILED" : "SMESH_COMPUTE_SUCCEED")); - myDlg->myMemoryLackGroup->hide(); + + if ( memoryLack ) + aMemoryReserve.release(); + + myCompDlg->setWindowTitle + ( tr( computeFailed ? "SMESH_WRN_COMPUTE_FAILED" : "SMESH_COMPUTE_SUCCEED" )); // SHOW ERRORS bool noCompError = ( !aCompErrors.operator->() || aCompErrors->length() == 0 ); bool noHypoError = ( aHypErrors.isEmpty() ); - if ( memoryLack ) + SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() ); + int aNotifyMode = resMgr->integerValue( "SMESH", "show_result_notification" ); + + bool isShowResultDlg = true; + switch( aNotifyMode ) { + case 0: // show the mesh computation result dialog NEVER + isShowResultDlg = false; + commit(); + break; + case 1: // show the mesh computation result dialog if there are some errors + if ( memoryLack || !noCompError || !noHypoError ) + isShowResultDlg = true; + else + { + isShowResultDlg = false; + commit(); + } + break; + default: // show the result dialog after each mesh computation + isShowResultDlg = true; + } + + // SHOW RESULTS + if ( isShowResultDlg ) + showComputeResult( memoryLack, noCompError,aCompErrors, noHypoError, aHypErrors ); +} + +void SMESHGUI_BaseComputeOp::showComputeResult( const bool theMemoryLack, + const bool theNoCompError, + SMESH::compute_error_array_var& theCompErrors, + const bool theNoHypoError, + const QString& theHypErrors ) +{ + bool hasShape = myMesh->HasShapeToMesh(); + SMESHGUI_ComputeDlg* aCompDlg = computeDlg(); + aCompDlg->myMemoryLackGroup->hide(); + + if ( theMemoryLack ) { - myDlg->myMemoryLackGroup->show(); - myDlg->myFullInfo->hide(); - myDlg->myBriefInfo->hide(); - myDlg->myHypErrorGroup->hide(); - myDlg->myCompErrorGroup->hide(); + aCompDlg->myMemoryLackGroup->show(); + aCompDlg->myFullInfo->hide(); + aCompDlg->myBriefInfo->hide(); + aCompDlg->myHypErrorGroup->hide(); + aCompDlg->myCompErrorGroup->hide(); } - else if ( noCompError && noHypoError ) + else if ( theNoCompError && theNoHypoError ) { - myDlg->myFullInfo->SetInfoByMesh( aMesh ); - myDlg->myFullInfo->show(); - myDlg->myBriefInfo->hide(); - myDlg->myHypErrorGroup->hide(); - myDlg->myCompErrorGroup->hide(); + SMESH::long_array_var aRes = myMesh->GetMeshInfo(); + aCompDlg->myFullInfo->SetMeshInfo( aRes ); + aCompDlg->myFullInfo->show(); + aCompDlg->myBriefInfo->hide(); + aCompDlg->myHypErrorGroup->hide(); + aCompDlg->myCompErrorGroup->hide(); } else { - QTable* tbl = myDlg->myTable; - myDlg->myBriefInfo->SetInfoByMesh( aMesh ); - myDlg->myBriefInfo->show(); - myDlg->myFullInfo->hide(); - - if ( noHypoError ) { - myDlg->myHypErrorGroup->hide(); + bool onlyWarnings = !theNoCompError; // == valid mesh computed but there are errors reported + for ( CORBA::ULong i = 0; i < theCompErrors->length() && onlyWarnings; ++i ) + onlyWarnings = ( theCompErrors[ i ].code == SMESH::COMPERR_WARNING || + theCompErrors[ i ].code == SMESH::COMPERR_NO_MESH_ON_SHAPE ); + + // full or brief mesh info + SMESH::long_array_var aRes = myMesh->GetMeshInfo(); + if ( onlyWarnings ) { + aCompDlg->myFullInfo->SetMeshInfo( aRes ); + aCompDlg->myFullInfo->show(); + aCompDlg->myBriefInfo->hide(); + } else { + aCompDlg->myBriefInfo->SetMeshInfo( aRes ); + aCompDlg->myBriefInfo->show(); + aCompDlg->myFullInfo->hide(); } - else { - myDlg->myHypErrorGroup->show(); - myDlg->myHypErrorLabel->setText( aHypErrors ); + + // pbs of hypo dfinitions + if ( theNoHypoError ) { + aCompDlg->myHypErrorGroup->hide(); + } else { + aCompDlg->myHypErrorGroup->show(); + aCompDlg->myHypErrorLabel->setText( theHypErrors ); } - if ( noCompError ) { - myDlg->myCompErrorGroup->hide(); + // table of errors + if ( theNoCompError ) + { + aCompDlg->myCompErrorGroup->hide(); } - else { - myDlg->myCompErrorGroup->show(); + else + { + aCompDlg->myCompErrorGroup->show(); + + if ( onlyWarnings ) + aCompDlg->myWarningLabel->show(); + else + aCompDlg->myWarningLabel->hide(); if ( !hasShape ) { - myDlg->myPublishBtn->hide(); - myDlg->myShowBtn->hide(); + aCompDlg->myPublishBtn->hide(); + aCompDlg->myShowBtn->hide(); } else { - myDlg->myPublishBtn->show(); - myDlg->myShowBtn->show(); + aCompDlg->myPublishBtn->show(); + aCompDlg->myShowBtn->show(); } // fill table of errors - tbl->setNumRows( aCompErrors->length() ); + QTableWidget* tbl = aCompDlg->myTable; + tbl->setRowCount( theCompErrors->length() ); if ( !hasShape ) tbl->hideColumn( COL_SHAPE ); else tbl->showColumn( COL_SHAPE ); tbl->setColumnWidth( COL_ERROR, 200 ); - for ( int row = 0; row < aCompErrors->length(); ++row ) + bool hasBadMesh = false; + for ( int row = 0; row < (int) theCompErrors->length(); ++row ) { - SMESH::ComputeError & err = aCompErrors[ row ]; - tbl->setText( row, COL_ALGO, err.algoName.in() ); - tbl->setText( row, COL_ERROR, errorText( err.code, err.comment.in() )); - tbl->setText( row, COL_SHAPEID, QString("%1").arg( err.subShapeID )); + SMESH::ComputeError & err = theCompErrors[ row ]; + + QString text = err.algoName.in(); + if ( !tbl->item( row, COL_ALGO ) ) tbl->setItem( row, COL_ALGO, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_ALGO )->setText( text ); + + text = SMESH::errorText( err.code, err.comment.in() ); + if ( !tbl->item( row, COL_ERROR ) ) tbl->setItem( row, COL_ERROR, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_ERROR )->setText( text ); + + text = QString("%1").arg( err.subShapeID ); + if ( !tbl->item( row, COL_SHAPEID ) ) tbl->setItem( row, COL_SHAPEID, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_SHAPEID )->setText( text ); - QString text = hasShape ? shapeText( err.subShapeID, myMainShape ) : QString(""); - tbl->setText( row, COL_SHAPE, text ); + text = hasShape ? SMESH::shapeText( err.subShapeID, myMainShape ) : QString(""); + if ( !tbl->item( row, COL_SHAPE ) ) tbl->setItem( row, COL_SHAPE, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_SHAPE )->setText( text ); - text = ( !hasShape || getSubShapeSO( err.subShapeID, myMainShape )) ? "PUBLISHED" : ""; - tbl->setText( row, COL_PUBLISHED, text ); // if text=="", "PUBLISH" button enabled + text = ( !hasShape || SMESH::getSubShapeSO( err.subShapeID, myMainShape )) ? "PUBLISHED" : ""; + if ( !tbl->item( row, COL_PUBLISHED ) ) tbl->setItem( row, COL_PUBLISHED, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_PUBLISHED )->setText( text ); // if text=="", "PUBLISH" button enabled - tbl->item( row, COL_ERROR )->setWordWrap( TRUE ); - tbl->adjustRow( row ); + text = err.hasBadMesh ? "hasBadMesh" : ""; + if ( !tbl->item( row, COL_BAD_MESH ) ) tbl->setItem( row, COL_BAD_MESH, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_BAD_MESH )->setText( text ); + if ( err.hasBadMesh ) hasBadMesh = true; + + //tbl->item( row, COL_ERROR )->setWordWrap( true ); // VSR: TODO ??? + tbl->resizeRowToContents( row ); } - tbl->adjustColumn( COL_ALGO ); - tbl->adjustColumn( COL_SHAPE ); + tbl->resizeColumnToContents( COL_ALGO ); + tbl->resizeColumnToContents( COL_SHAPE ); + tbl->setWordWrap( true ); + if ( hasBadMesh ) { + aCompDlg->myBadMeshBtn->show(); + aCompDlg->myBadMeshToGroupBtn->show(); + } + else { + aCompDlg->myBadMeshBtn->hide(); + aCompDlg->myBadMeshToGroupBtn->hide(); + } tbl->setCurrentCell(0,0); currentCellChanged(); // to update buttons } } - myDlg->show(); + // show dialog and wait, becase Compute can be invoked from Preview operation + //aCompDlg->exec(); // this way it becomes modal - impossible to rotate model in the Viewer + aCompDlg->show(); } //================================================================================ @@ -982,83 +1244,177 @@ void SMESHGUI_ComputeOp::startOperation() */ //================================================================================ -void SMESHGUI_ComputeOp::stopOperation() +void SMESHGUI_BaseComputeOp::stopOperation() { SMESHGUI_Operation::stopOperation(); - myTShapeDisplayer->SetVisibility( false ); + if ( myTShapeDisplayer ) + myTShapeDisplayer->SetVisibility( false ); + if ( myBadMeshDisplayer ) { + myBadMeshDisplayer->SetVisibility( false ); + // delete it in order not to have problems at its destruction when the viewer + // where it worked is dead due to e.g. study closing + delete myBadMeshDisplayer; + myBadMeshDisplayer = 0; + } + myIObject.Nullify(); } //================================================================================ /*! - * \brief publish selected subshape + * \brief publish selected sub-shape */ //================================================================================ -void SMESHGUI_ComputeOp::onPublishShape() +void SMESHGUI_BaseComputeOp::onPublishShape() { - GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen(); - SALOMEDS::Study_var study = SMESHGUI::GetSMESHGen()->GetCurrentStudy(); - - list< int > rows; - list< int >::iterator row; - getSelectedRows( table(), rows ); - for ( row = rows.begin(); row != rows.end(); ++row ) + GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen(); + SALOMEDS::Study_var study = SMESHGUI::GetSMESHGen()->GetCurrentStudy(); + GEOM::GEOM_Object_var meshShape = myMesh->GetShapeToMesh(); + + QStringList entryList; + QList rows; + SMESH::getSelectedRows( table(), rows ); + int row; + foreach ( row, rows ) { - int curSub = table()->text(*row, COL_SHAPEID).toInt(); - GEOM::GEOM_Object_var shape = getSubShape( curSub, myMainShape ); - if ( !shape->_is_nil() && ! getSubShapeSO( curSub, myMainShape )) + int curSub = table()->item(row, COL_SHAPEID)->text().toInt(); + GEOM::GEOM_Object_wrap shape = SMESH::getSubShape( curSub, myMainShape ); + if ( !shape->_is_nil() && ! SMESH::getSubShapeSO( curSub, myMainShape )) { - if ( !getSubShapeSO( 1, myMainShape )) // the main shape not published + if ( !SMESH::getSubShapeSO( 1, myMainShape )) // the main shape not published { - QString name = GEOMBase::GetDefaultName( shapeTypeName( myMainShape, "MAIN_SHAPE" )); - SALOMEDS::SObject_var so = - geomGen->AddInStudy( study, myMainShape, name, GEOM::GEOM_Object::_nil()); + QString name = GEOMBase::GetDefaultName( SMESH::shapeTypeName( myMainShape, "MAIN_SHAPE" )); + SALOMEDS::SObject_wrap so = geomGen->AddInStudy( study, myMainShape, + name.toLatin1().data(), + GEOM::GEOM_Object::_nil()); // look for myMainShape in the table - for ( int r = 0, nr = table()->numRows(); r < nr; ++r ) { - if ( table()->text(r, COL_SHAPEID) == "1" ) { + for ( int r = 0, nr = table()->rowCount(); r < nr; ++r ) { + if ( table()->item( r, COL_SHAPEID )->text() == "1" ) { if ( so->_is_nil() ) { - table()->setText( r, COL_SHAPE, so->GetName() ); - table()->setText( r, COL_PUBLISHED, so->GetID() ); + CORBA::String_var name = so->GetName(); + CORBA::String_var entry = so->GetID(); + QString shapeText = QString("%1 (%2)").arg( name.in() ).arg( entry.in() ); + table()->item( r, COL_SHAPE )->setText( shapeText ); + table()->item( r, COL_PUBLISHED )->setText( entry.in() ); } break; } } if ( curSub == 1 ) continue; } - QString name = GEOMBase::GetDefaultName( shapeTypeName( shape, "ERROR_SHAPE" )); - SALOMEDS::SObject_var so = geomGen->AddInStudy( study, shape, name, myMainShape); + QString name = GEOMBase::GetDefaultName( SMESH::shapeTypeName( shape, "ERROR_SHAPE" )); + SALOMEDS::SObject_wrap so = geomGen->AddInStudy( study, shape, + name.toLatin1().data(), myMainShape); if ( !so->_is_nil() ) { - table()->setText( *row, COL_SHAPE, so->GetName() ); - table()->setText( *row, COL_PUBLISHED, so->GetID() ); + CORBA::String_var name = so->GetName(); + CORBA::String_var entry = so->GetID(); + QString shapeText = QString("%1 (%2)").arg( name.in() ).arg( entry.in() ); + table()->item( row, COL_SHAPE )->setText( shapeText ); + table()->item( row, COL_PUBLISHED )->setText( entry.in() ); + entryList.push_back( entry.in() ); } } } getSMESHGUI()->getApp()->updateObjectBrowser(); + getSMESHGUI()->getApp()->browseObjects( entryList, /*isApplyAndClose=*/true ); + currentCellChanged(); // to update buttons } //================================================================================ /*! - * \brief SLOT called when a selected cell in table() changed + * \brief show mesh elements preventing computation of a submesh of current row */ //================================================================================ -void SMESHGUI_ComputeOp::currentCellChanged() +void SMESHGUI_BaseComputeOp::onShowBadMesh() { myTShapeDisplayer->SetVisibility( false ); + QList rows; + if ( SMESH::getSelectedRows( table(), rows ) == 1 ) { + bool hasBadMesh = ( !table()->item(rows.front(), COL_BAD_MESH)->text().isEmpty() ); + if ( hasBadMesh ) { + int curSub = table()->item(rows.front(), COL_SHAPEID)->text().toInt(); + SMESHGUI* gui = getSMESHGUI(); + SMESH::SMESH_Gen_var gen = gui->GetSMESHGen(); + SVTK_ViewWindow* view = SMESH::GetViewWindow( gui ); + if ( myBadMeshDisplayer ) delete myBadMeshDisplayer; + myBadMeshDisplayer = new SMESHGUI_MeshEditPreview( view ); + SMESH::MeshPreviewStruct_var aMeshData = gen->GetBadInputElements(myMesh,curSub); + double aPointSize = SMESH::GetFloat("SMESH:node_size",3); + double aLineWidth = SMESH::GetFloat("SMESH:element_width",1); + vtkProperty* prop = vtkProperty::New(); + prop->SetLineWidth( aLineWidth * 3 ); + prop->SetPointSize( aPointSize * 3 ); + prop->SetColor( 250, 0, 250 ); + myBadMeshDisplayer->GetActor()->SetProperty( prop ); + myBadMeshDisplayer->SetData( aMeshData._retn() ); + prop->Delete(); + } + } +} + +//================================================================================ +/*! + * \brief create groups of bad mesh elements preventing computation of a submesh of current row + */ +//================================================================================ + +void SMESHGUI_BaseComputeOp::onGroupOfBadMesh() +{ + QList rows; + SMESH::getSelectedRows( table(), rows ); + int row; + foreach ( row, rows ) + { + bool hasBadMesh = ( !table()->item(row, COL_BAD_MESH)->text().isEmpty() ); + if ( hasBadMesh ) { + int curSub = table()->item(rows.front(), COL_SHAPEID)->text().toInt(); + QString grName = table()->item(rows.front(), COL_SHAPE)->text(); + if ( grName.isEmpty() ) grName = "bad mesh"; + else grName = "bad mesh of " + grName; + SMESH::SMESH_Gen_var gen = getSMESHGUI()->GetSMESHGen(); + SMESH::ListOfGroups_var groups + ( gen->MakeGroupsOfBadInputElements(myMesh,curSub,grName.toLatin1().data()) ); + update( UF_ObjBrowser | UF_Model ); + if( LightApp_Application* anApp = dynamic_cast( application() )) + { + QStringList anEntryList; + for ( size_t i = 0; i < groups->length(); ++i ) + if ( _PTR(SObject) so = SMESH::FindSObject( groups[i] )) + anEntryList.append( so->GetID().c_str() ); + + if ( !anEntryList.isEmpty()) + anApp->browseObjects( anEntryList, true, false ); + } + } + } +} + +//================================================================================ +/*! + * \brief SLOT called when a selected cell in table() changed + */ +//================================================================================ - bool publishEnable = 0, showEnable = 0, showOnly = 1; - list< int > rows; - list< int >::iterator row; - getSelectedRows( table(), rows ); - for ( row = rows.begin(); row != rows.end(); ++row ) +void SMESHGUI_BaseComputeOp::currentCellChanged() +{ + myTShapeDisplayer->SetVisibility( false ); + if ( myBadMeshDisplayer ) + myBadMeshDisplayer->SetVisibility( false ); + + bool publishEnable = 0, showEnable = 0, showOnly = 1, hasBadMesh = 0; + QList rows; + int nbSelected = SMESH::getSelectedRows( table(), rows ); + int row; + foreach ( row, rows ) { - bool hasData = ( !table()->text(*row, COL_SHAPE).isEmpty() ); - bool isPublished = ( !table()->text(*row, COL_PUBLISHED).isEmpty() ); + bool hasData = ( !table()->item( row, COL_SHAPE )->text().isEmpty() ); + bool isPublished = ( !table()->item( row, COL_PUBLISHED )->text().isEmpty() ); if ( hasData && !isPublished ) publishEnable = true; - int curSub = table()->text(*row, COL_SHAPEID).toInt(); + int curSub = table()->item( row, COL_SHAPEID )->text().toInt(); bool prsReady = myTShapeDisplayer->HasReadyActorsFor( curSub, myMainShape ); if ( prsReady ) { myTShapeDisplayer->Show( curSub, myMainShape, showOnly ); @@ -1067,9 +1423,14 @@ void SMESHGUI_ComputeOp::currentCellChanged() else { showEnable = true; } + + if ( !table()->item(row, COL_BAD_MESH)->text().isEmpty() ) + hasBadMesh = true; } - myDlg->myPublishBtn->setEnabled( publishEnable ); - myDlg->myShowBtn->setEnabled( showEnable ); + myCompDlg->myPublishBtn->setEnabled( publishEnable ); + myCompDlg->myShowBtn ->setEnabled( showEnable ); + myCompDlg->myBadMeshBtn->setEnabled( hasBadMesh && ( nbSelected == 1 )); + myCompDlg->myBadMeshToGroupBtn->setEnabled( hasBadMesh && ( nbSelected == 1 )); } //================================================================================ @@ -1078,19 +1439,19 @@ void SMESHGUI_ComputeOp::currentCellChanged() */ //================================================================================ -void SMESHGUI_ComputeOp::onPreviewShape() +void SMESHGUI_BaseComputeOp::onPreviewShape() { if ( myTShapeDisplayer ) { SUIT_OverrideCursor aWaitCursor; - list< int > rows; - list< int >::iterator row; - getSelectedRows( table(), rows ); + QList rows; + SMESH::getSelectedRows( table(), rows ); bool showOnly = true; - for ( row = rows.begin(); row != rows.end(); ++row ) + int row; + foreach ( row, rows ) { - int curSub = table()->text(*row, COL_SHAPEID).toInt(); + int curSub = table()->item( row, COL_SHAPEID )->text().toInt(); if ( curSub > 0 ) { myTShapeDisplayer->Show( curSub, myMainShape, showOnly ); showOnly = false; @@ -1106,30 +1467,48 @@ void SMESHGUI_ComputeOp::onPreviewShape() */ //================================================================================ -SMESHGUI_ComputeOp::~SMESHGUI_ComputeOp() +SMESHGUI_BaseComputeOp::~SMESHGUI_BaseComputeOp() { - if ( myTShapeDisplayer ) delete myTShapeDisplayer; + delete myCompDlg; + myCompDlg = 0; + delete myTShapeDisplayer; + if ( myBadMeshDisplayer ) + delete myBadMeshDisplayer; } //================================================================================ /*! - * \brief Gets dialog of this operation - * \retval LightApp_Dialog* - pointer to dialog of this operation + * \brief Gets dialog of compute operation + * \retval SMESHGUI_ComputeDlg* - pointer to dialog of this operation */ //================================================================================ -LightApp_Dialog* SMESHGUI_ComputeOp::dlg() const +SMESHGUI_ComputeDlg* SMESHGUI_BaseComputeOp::computeDlg() const { - return myDlg; + if ( !myCompDlg ) + { + SMESHGUI_BaseComputeOp* me = (SMESHGUI_BaseComputeOp*)this; + me->myCompDlg = new SMESHGUI_ComputeDlg( desktop(), false ); + // connect signals and slots + connect(myCompDlg->myShowBtn, SIGNAL (clicked()), SLOT(onPreviewShape())); + connect(myCompDlg->myPublishBtn, SIGNAL (clicked()), SLOT(onPublishShape())); + connect(myCompDlg->myBadMeshBtn, SIGNAL (clicked()), SLOT(onShowBadMesh())); + connect(myCompDlg->myBadMeshToGroupBtn, SIGNAL (clicked()), SLOT(onGroupOfBadMesh())); + + QTableWidget* aTable = me->table(); + connect(aTable, SIGNAL(itemSelectionChanged()), SLOT(currentCellChanged())); + connect(aTable, SIGNAL(currentCellChanged(int,int,int,int)), SLOT(currentCellChanged())); + } + return myCompDlg; } //================================================================================ /*! - * \brief perform it's intention action: compute mesh + * \brief returns from compute mesh result dialog */ //================================================================================ -bool SMESHGUI_ComputeOp::onApply() +bool SMESHGUI_BaseComputeOp::onApply() { return true; } @@ -1140,7 +1519,912 @@ bool SMESHGUI_ComputeOp::onApply() */ //================================================================================ -QTable* SMESHGUI_ComputeOp::table() +QTableWidget* SMESHGUI_BaseComputeOp::table() +{ + return myCompDlg->myTable; +} + + +//================================================================================ +/*! + * \brief Constructor +*/ +//================================================================================ + +SMESHGUI_ComputeOp::SMESHGUI_ComputeOp() + : SMESHGUI_BaseComputeOp() { - return myDlg->myTable; + myHelpFileName = "constructing_meshes_page.html#compute_anchor"; } + + +//================================================================================ +/*! + * \brief Desctructor +*/ +//================================================================================ + +SMESHGUI_ComputeOp::~SMESHGUI_ComputeOp() +{ +} + +//================================================================================ +/*! + * \brief perform it's intention action: compute mesh + */ +//================================================================================ + +void SMESHGUI_ComputeOp::startOperation() +{ + SMESHGUI_BaseComputeOp::startOperation(); + if (myMesh->_is_nil()) + return; + computeMesh(); +} + +//================================================================================ +/*! + * \brief check the same operations on the same mesh + */ +//================================================================================ + +bool SMESHGUI_BaseComputeOp::isValid( SUIT_Operation* theOp ) const +{ + SMESHGUI_BaseComputeOp* baseOp = dynamic_cast( theOp ); + bool ret = true; + if ( !myMesh->_is_nil() && baseOp ) { + SMESH::SMESH_Mesh_var aMesh = baseOp->getMesh(); + if ( !aMesh->_is_nil() && aMesh->GetId() == myMesh->GetId() ) ret = false; + } + return ret; +} + +//================================================================================ +/*! + * \brief Gets dialog of this operation + * \retval LightApp_Dialog* - pointer to dialog of this operation + */ +//================================================================================ + +LightApp_Dialog* SMESHGUI_ComputeOp::dlg() const +{ + return computeDlg(); +} + +//================================================================================ +/*! + * \brief Constructor + */ +//================================================================================ + +SMESHGUI_PrecomputeOp::SMESHGUI_PrecomputeOp() + : SMESHGUI_BaseComputeOp(), + myActiveDlg( 0 ), + myDlg( 0 ), + myPreviewDisplayer( 0 ), + myOrderMgr( 0 ) +{ +} + +//================================================================================ +/*! + * \brief Destructor + */ +//================================================================================ + +SMESHGUI_PrecomputeOp::~SMESHGUI_PrecomputeOp() +{ + delete myDlg; + myDlg = 0; + delete myOrderMgr; + myOrderMgr = 0; + myActiveDlg = 0; + if ( myPreviewDisplayer ) + delete myPreviewDisplayer; + myPreviewDisplayer = 0; +} + +//================================================================================ +/*! + * \brief Gets current dialog of this operation + * \retval LightApp_Dialog* - pointer to dialog of this operation + */ +//================================================================================ + +LightApp_Dialog* SMESHGUI_PrecomputeOp::dlg() const +{ + return myActiveDlg; +} + +//================================================================================ +/*! + * \brief perform it's intention action: prepare data + */ +//================================================================================ + +void SMESHGUI_PrecomputeOp::startOperation() +{ + myHelpFileName = "constructing_meshes_page.html#preview_anchor"; // other anchor onCompute() + + if ( !myDlg ) + { + myDlg = new SMESHGUI_PrecomputeDlg( desktop() ); + + // connect signals + connect( myDlg, SIGNAL( preview() ), this, SLOT( onPreview() ) ); + connect( myDlg, SIGNAL( dlgOk() ), this, SLOT( onCompute() ) ); + connect( myDlg, SIGNAL( dlgApply() ), this, SLOT( onCompute() ) ); + } + myActiveDlg = myDlg; + + // connect signal to compute dialog. which will be shown after Compute mesh operation + SMESHGUI_ComputeDlg* cmpDlg = computeDlg(); + if ( cmpDlg ) + { + // disconnect signals + disconnect( cmpDlg, SIGNAL( dlgOk() ), this, SLOT( onOk() ) ); + disconnect( cmpDlg, SIGNAL( dlgApply() ), this, SLOT( onApply() ) ); + disconnect( cmpDlg, SIGNAL( dlgCancel() ), this, SLOT( onCancel() ) ); + disconnect( cmpDlg, SIGNAL( dlgClose() ), this, SLOT( onCancel() ) ); + disconnect( cmpDlg, SIGNAL( dlgHelp() ), this, SLOT( onHelp() ) ); + + // connect signals + if( cmpDlg->testButtonFlags( QtxDialog::OK ) ) + connect( cmpDlg, SIGNAL( dlgOk() ), this, SLOT( onOk() ) ); + if( cmpDlg->testButtonFlags( QtxDialog::Apply ) ) + connect( cmpDlg, SIGNAL( dlgApply() ), this, SLOT( onApply() ) ); + if( cmpDlg->testButtonFlags( QtxDialog::Help ) ) + connect( cmpDlg, SIGNAL( dlgHelp() ), this, SLOT( onHelp() ) ); + if( cmpDlg->testButtonFlags( QtxDialog::Cancel ) ) + connect( cmpDlg, SIGNAL( dlgCancel() ), this, SLOT( onCancel() ) ); + if( cmpDlg->testButtonFlags( QtxDialog::Close ) ) + connect( cmpDlg, SIGNAL( dlgClose() ), this, SLOT( onCancel() ) ); + } + + SMESHGUI_BaseComputeOp::startOperation(); + if (myMesh->_is_nil()) + return; + + if (myDlg->getPreviewMode() == -1) + { + // nothing to preview + SUIT_MessageBox::warning(desktop(), + tr("SMESH_WRN_WARNING"), + tr("SMESH_WRN_NOTHING_PREVIEW")); + onCancel(); + return; + } + + // disconnect slot from preview dialog to have Apply from results of compute operation only + disconnect( myDlg, SIGNAL( dlgOk() ), this, SLOT( onOk() ) ); + disconnect( myDlg, SIGNAL( dlgApply() ), this, SLOT( onApply() ) ); + + myDlg->show(); +} + +//================================================================================ +/*! + * \brief Stops operation + */ +//================================================================================ + +void SMESHGUI_PrecomputeOp::stopOperation() +{ + if ( myPreviewDisplayer ) + { + myPreviewDisplayer->SetVisibility( false ); + delete myPreviewDisplayer; + myPreviewDisplayer = 0; + } + myMapShapeId.clear(); + SMESHGUI_BaseComputeOp::stopOperation(); +} + +//================================================================================ +/*! + * \brief reinitialize dialog after operaiton become active again + */ +//================================================================================ + +void SMESHGUI_PrecomputeOp::resumeOperation() +{ + if ( myActiveDlg == myDlg ) + initDialog(); + SMESHGUI_BaseComputeOp::resumeOperation(); +} + +//================================================================================ +/*! + * \brief perform it's intention action: reinitialise dialog + */ +//================================================================================ + +void SMESHGUI_PrecomputeOp::initDialog() +{ + QList modes; + + QMap modeMap; + _PTR(SObject) pMesh = studyDS()->FindObjectID( myIObject->getEntry() ); + getAssignedAlgos( pMesh, modeMap ); + if ( modeMap.contains( SMESH::DIM_3D ) ) + { + if ( modeMap.contains( SMESH::DIM_2D ) ) + modes.append( SMESH::DIM_2D ); + if ( modeMap.contains( SMESH::DIM_1D ) ) + modes.append( SMESH::DIM_1D ); + } + else if ( modeMap.contains( SMESH::DIM_2D ) ) + { + if ( modeMap.contains( SMESH::DIM_1D ) ) + modes.append( SMESH::DIM_1D ); + } + + myOrderMgr = new SMESHGUI_MeshOrderMgr( myDlg->getMeshOrderBox() ); + myOrderMgr->SetMesh( myMesh ); + bool isOrder = myOrderMgr->GetMeshOrder(myPrevOrder); + myDlg->getMeshOrderBox()->setVisible(isOrder); + if ( !isOrder ) { + delete myOrderMgr; + myOrderMgr = 0; + } + + myDlg->setPreviewModes( modes ); +} + +//================================================================================ +/*! + * \brief detect asigned mesh algorithms + */ +//================================================================================ + +void SMESHGUI_PrecomputeOp::getAssignedAlgos(_PTR(SObject) theMesh, + QMap& theModeMap) +{ + if ( !theMesh ) return; + + _PTR(SObject) aHypFolder; + _PTR(GenericAttribute) anAttr; + int aPart = SMESH::Tag_RefOnAppliedAlgorithms; + if ( theMesh->FindSubObject( aPart, aHypFolder )) + { + _PTR(ChildIterator) anIter = + SMESH::GetActiveStudyDocument()->NewChildIterator( aHypFolder ); + for ( ; anIter->More(); anIter->Next() ) + { + _PTR(SObject) anObj = anIter->Value(); + _PTR(SObject) aRefObj; + if ( anObj->ReferencedObject( aRefObj ) ) + anObj = aRefObj; + else + continue; + + if ( anObj->FindAttribute( anAttr, "AttributeName" ) ) + { + CORBA::Object_var aVar = _CAST(SObject,anObj)->GetObject(); + if ( CORBA::is_nil( aVar ) ) + continue; + + SMESH::SMESH_Algo_var algo; + for( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ ) + { + switch(dim) { + case SMESH::DIM_1D: algo = SMESH::SMESH_1D_Algo::_narrow( aVar ); break; + case SMESH::DIM_2D: algo = SMESH::SMESH_2D_Algo::_narrow( aVar ); break; + case SMESH::DIM_3D: algo = SMESH::SMESH_3D_Algo::_narrow( aVar ); break; + default: break; + } + if ( !algo->_is_nil() ) + { + theModeMap[ dim ] = 0; + if ( theModeMap.size() == 3 ) + return; + break; + } + } + } + } + } + + // check sub-meshes + for ( aPart = SMESH::Tag_SubMeshOnEdge; aPart <= SMESH::Tag_LastSubMesh; ++aPart ) + { + if ( !theMesh->FindSubObject( aPart, aHypFolder )) + continue; + + _PTR(ChildIterator) anIter = + SMESH::GetActiveStudyDocument()->NewChildIterator( aHypFolder ); + for ( anIter->InitEx(true); anIter->More(); anIter->Next() ) + { + _PTR(SObject) anObj = anIter->Value(); + _PTR(SObject) aRefObj; + if ( anObj->ReferencedObject( aRefObj ) ) + anObj = aRefObj; + else + continue; + + if ( anObj->FindAttribute( anAttr, "AttributeName" )) + { + CORBA::Object_var aVar = _CAST(SObject,anObj)->GetObject(); + if ( CORBA::is_nil( aVar ) ) + continue; + + SMESH::SMESH_Algo_var algo; + for( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ ) + { + switch(dim) { + case SMESH::DIM_1D: algo = SMESH::SMESH_1D_Algo::_narrow( aVar ); break; + case SMESH::DIM_2D: algo = SMESH::SMESH_2D_Algo::_narrow( aVar ); break; + case SMESH::DIM_3D: algo = SMESH::SMESH_3D_Algo::_narrow( aVar ); break; + default: break; + } + if ( !algo->_is_nil() ) + { + theModeMap[ dim ] = 0; + if ( theModeMap.size() == 3 ) + return; + break; + } + } + } + } + } +} + +//================================================================================ +/*! + * \brief perform it's intention action: compute mesh + */ +//================================================================================ + +void SMESHGUI_PrecomputeOp::onCompute() +{ + myDlg->hide(); + if (myOrderMgr && myOrderMgr->IsOrderChanged()) + myOrderMgr->SetMeshOrder(); + myMapShapeId.clear(); + myActiveDlg = computeDlg(); + myHelpFileName = "constructing_meshes_page.html#compute_anchor"; + computeMesh(); +} + +//================================================================================ +/*! + * \brief perform it's intention action: compute mesh + */ +//================================================================================ + +void SMESHGUI_PrecomputeOp::onCancel() +{ + QObject* curDlg = sender(); + if ( curDlg == computeDlg() && myActiveDlg == myDlg ) + { + // return from error messages + myDlg->show(); + return; + } + + bool isRestoreOrder = false; + if ( myActiveDlg == myDlg && !myMesh->_is_nil() && myMapShapeId.count() ) + { + // ask to remove already computed mesh elements + if ( SUIT_MessageBox::question( desktop(), tr( "SMESH_WARNING" ), + tr( "CLEAR_SUBMESH_QUESTION" ), + tr( "SMESH_BUT_DELETE" ), tr( "SMESH_BUT_NO" ), 0, 1 ) == 0 ) + { + // remove all submeshes for collected shapes + QMap::const_iterator it = myMapShapeId.constBegin(); + for ( ; it != myMapShapeId.constEnd(); ++it ) + myMesh->ClearSubMesh( it.key() ); + isRestoreOrder = true; + } + } + + // return previous mesh order + if (myOrderMgr && myOrderMgr->IsOrderChanged()) { + if (!isRestoreOrder) + isRestoreOrder = + (SUIT_MessageBox::question( desktop(), tr( "SMESH_WARNING" ), + tr( "SMESH_REJECT_MESH_ORDER" ), + tr( "SMESH_BUT_YES" ), tr( "SMESH_BUT_NO" ), 0, 1 ) == 0); + if (isRestoreOrder) + myOrderMgr->SetMeshOrder(myPrevOrder); + } + + delete myOrderMgr; + myOrderMgr = 0; + + myMapShapeId.clear(); + SMESHGUI_BaseComputeOp::onCancel(); +} + +//================================================================================ +/*! + * \brief perform it's intention action: preview mesh + */ +//================================================================================ + +void SMESHGUI_PrecomputeOp::onPreview() +{ + if ( !myDlg || myMesh->_is_nil() || myMainShape->_is_nil() ) + return; + + _PTR(SObject) aMeshSObj = SMESH::FindSObject(myMesh); + if ( !aMeshSObj ) + return; + + // set modified submesh priority if any + if (myOrderMgr && myOrderMgr->IsOrderChanged()) + myOrderMgr->SetMeshOrder(); + + // Compute preview of mesh, + // i.e. compute mesh till indicated dimension + int dim = myDlg->getPreviewMode(); + + SMESH::MemoryReserve aMemoryReserve; + + SMESH::compute_error_array_var aCompErrors; + QString aHypErrors; + + bool computeFailed = true, memoryLack = false; + + SMESHGUI_ComputeDlg* aCompDlg = computeDlg(); + aCompDlg->myMeshName->setText( aMeshSObj->GetName().c_str() ); + + SMESHGUI* gui = getSMESHGUI(); + SMESH::SMESH_Gen_var gen = gui->GetSMESHGen(); + SMESH::algo_error_array_var errors = gen->GetAlgoState(myMesh,myMainShape); + if ( errors->length() > 0 ) { + aHypErrors = SMESH::GetMessageOnAlgoStateErrors( errors.in() ); + } + + SUIT_OverrideCursor aWaitCursor; + + SVTK_ViewWindow* view = SMESH::GetViewWindow( gui ); + if ( myPreviewDisplayer ) delete myPreviewDisplayer; + myPreviewDisplayer = new SMESHGUI_MeshEditPreview( view ); + + SMESH::long_array_var aShapesId = new SMESH::long_array(); + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif + + SMESH::MeshPreviewStruct_var previewData = + gen->Precompute(myMesh, myMainShape, (SMESH::Dimension)dim, aShapesId); + + SMESH::MeshPreviewStruct* previewRes = previewData._retn(); + if ( previewRes && previewRes->nodesXYZ.length() > 0 ) + { + computeFailed = false; + myPreviewDisplayer->SetData( previewRes ); + // append shape indeces with computed mesh entities + for ( int i = 0, n = aShapesId->length(); i < n; i++ ) + myMapShapeId[ aShapesId[ i ] ] = 0; + } + else + myPreviewDisplayer->SetVisibility(false); + } + catch(const SALOME::SALOME_Exception & S_ex){ + memoryLack = true; + myPreviewDisplayer->SetVisibility(false); + } + + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif + aCompErrors = gen->GetComputeErrors( myMesh, myMainShape ); + // check if there are memory problems + for ( CORBA::ULong i = 0; (i < aCompErrors->length()) && !memoryLack; ++i ) + memoryLack = ( aCompErrors[ i ].code == SMESH::COMPERR_MEMORY_PB ); + } + catch(const SALOME::SALOME_Exception & S_ex){ + memoryLack = true; + } + + if ( memoryLack ) + aMemoryReserve.release(); + + bool noCompError = ( !aCompErrors.operator->() || aCompErrors->length() == 0 ); + bool noHypoError = ( aHypErrors.isEmpty() ); + + SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( gui ); + int aNotifyMode = resMgr->integerValue( "SMESH", "show_result_notification" ); + + bool isShowError = true; + switch( aNotifyMode ) { + case 0: // show the mesh computation result dialog NEVER + isShowError = false; + break; + case 1: // show the mesh computation result dialog if there are some errors + default: // show the result dialog after each mesh computation + if ( !computeFailed && !memoryLack && noCompError && noHypoError ) + isShowError = false; + break; + } + + aWaitCursor.suspend(); + // SHOW ERRORS + if ( isShowError ) + { + myDlg->hide(); + aCompDlg->setWindowTitle + ( tr( computeFailed ? "SMESH_WRN_COMPUTE_FAILED" : "SMESH_COMPUTE_SUCCEED" )); + showComputeResult( memoryLack, noCompError, aCompErrors, noHypoError, aHypErrors ); + } +} + + +//================================================================================ +/*! + * \brief Constructor +*/ +//================================================================================ + +SMESHGUI_PrecomputeDlg::SMESHGUI_PrecomputeDlg( QWidget* parent ) + : SMESHGUI_Dialog( parent, false, false, OK | Cancel | Help ), + myOrderBox(0) +{ + setWindowTitle( tr( "CAPTION" ) ); + + setButtonText( OK, tr( "COMPUTE" ) ); + QFrame* main = mainFrame(); + main->setMinimumWidth( 300 ); + + QVBoxLayout* layout = new QVBoxLayout( main ); + + myOrderBox = new SMESHGUI_MeshOrderBox( main ); + layout->addWidget(myOrderBox); + + QFrame* frame = new QFrame( main ); + layout->setMargin(0); layout->setSpacing(0); + layout->addWidget( frame ); + + QHBoxLayout* frameLay = new QHBoxLayout( frame ); + frameLay->setMargin(0); frameLay->setSpacing(SPACING); + + myPreviewMode = new QtxComboBox( frame ); + frameLay->addWidget( myPreviewMode ); + + myPreviewBtn = new QPushButton( tr( "PREVIEW" ), frame ); + frameLay->addWidget( myPreviewBtn ); + + connect( myPreviewBtn, SIGNAL( clicked( bool ) ), this, SIGNAL( preview() ) ); +} + +//================================================================================ +/*! + * \brief Destructor +*/ +//================================================================================ + +SMESHGUI_PrecomputeDlg::~SMESHGUI_PrecomputeDlg() +{ +} + +//================================================================================ +/*! + * \brief Sets available preview modes +*/ +//================================================================================ + +void SMESHGUI_PrecomputeDlg::setPreviewModes( const QList& theModes ) +{ + myPreviewMode->clear(); + QList::const_iterator it = theModes.constBegin(); + for ( int i = 0; it != theModes.constEnd(); ++it, i++ ) + { + QString mode = QString( "PREVIEW_%1" ).arg( *it ); + myPreviewMode->addItem( tr( mode.toLatin1().data() ) ); + myPreviewMode->setId( i, *it ); + } + myPreviewBtn->setEnabled( !theModes.isEmpty() ); +} + +//================================================================================ +/*! + * \brief Returns current preview mesh mode +*/ +//================================================================================ + +int SMESHGUI_PrecomputeDlg::getPreviewMode() const +{ + return myPreviewMode->currentId().toInt(); +} + +//================================================================================ +/*! + * \brief Returns current preview mesh mode +*/ +//================================================================================ + +SMESHGUI_MeshOrderBox* SMESHGUI_PrecomputeDlg::getMeshOrderBox() const +{ + return myOrderBox; +} + + +//================================================================================ +/*! + * \brief Constructor +*/ +//================================================================================ + +SMESHGUI_EvaluateOp::SMESHGUI_EvaluateOp() + : SMESHGUI_BaseComputeOp() +{ + myHelpFileName = "constructing_meshes_page.html#evaluate_anchor"; +} + + +//================================================================================ +/*! + * \brief Desctructor +*/ +//================================================================================ + +SMESHGUI_EvaluateOp::~SMESHGUI_EvaluateOp() +{ +} + +//================================================================================ +/*! + * \brief perform it's intention action: compute mesh + */ +//================================================================================ + +void SMESHGUI_EvaluateOp::startOperation() +{ + SMESHGUI_BaseComputeOp::evaluateDlg(); + SMESHGUI_BaseComputeOp::startOperation(); + if (myMesh->_is_nil()) + return; + evaluateMesh(); +} + +//================================================================================ +/*! + * \brief Gets dialog of this operation + * \retval LightApp_Dialog* - pointer to dialog of this operation + */ +//================================================================================ + +LightApp_Dialog* SMESHGUI_EvaluateOp::dlg() const +{ + return evaluateDlg(); +} + +//================================================================================ +/*! + * \brief evaluateMesh() +*/ +//================================================================================ + +void SMESHGUI_BaseComputeOp::evaluateMesh() +{ + // EVALUATE MESH + + SMESH::MemoryReserve aMemoryReserve; + + SMESH::compute_error_array_var aCompErrors; + QString aHypErrors; + + bool evaluateFailed = true, memoryLack = false; + SMESH::long_array_var aRes; + + _PTR(SObject) aMeshSObj = SMESH::FindSObject(myMesh); + if ( !aMeshSObj ) // IPAL21340 + return; + + bool hasShape = myMesh->HasShapeToMesh(); + bool shapeOK = myMainShape->_is_nil() ? !hasShape : hasShape; + if ( shapeOK ) + { + myCompDlg->myMeshName->setText( aMeshSObj->GetName().c_str() ); + SMESH::SMESH_Gen_var gen = getSMESHGUI()->GetSMESHGen(); + SMESH::algo_error_array_var errors = gen->GetAlgoState(myMesh,myMainShape); + if ( errors->length() > 0 ) { + aHypErrors = SMESH::GetMessageOnAlgoStateErrors( errors.in() ); + } + SUIT_OverrideCursor aWaitCursor; + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif + aRes = gen->Evaluate(myMesh, myMainShape); + } + catch(const SALOME::SALOME_Exception & S_ex){ + memoryLack = true; + } + + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif + aCompErrors = gen->GetComputeErrors( myMesh, myMainShape ); + } + catch(const SALOME::SALOME_Exception & S_ex){ + memoryLack = true; + } + } + + if ( memoryLack ) + aMemoryReserve.release(); + + evaluateFailed = ( aCompErrors->length() > 0 ); + myCompDlg->setWindowTitle + ( tr( evaluateFailed ? "SMESH_WRN_EVALUATE_FAILED" : "SMESH_EVALUATE_SUCCEED" )); + + // SHOW ERRORS + + bool noCompError = ( !aCompErrors.operator->() || aCompErrors->length() == 0 ); + bool noHypoError = ( aHypErrors.isEmpty() ); + + //SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() ); + //int aNotifyMode = resMgr->integerValue( "SMESH", "show_result_notification" ); + + bool isShowResultDlg = true; + //if( noHypoError ) + //switch( aNotifyMode ) { + //case 0: // show the mesh computation result dialog NEVER + //isShowResultDlg = false; + //commit(); + //break; + //case 1: // show the mesh computation result dialog if there are some errors + //if ( memoryLack || !noHypoError ) + // isShowResultDlg = true; + //else + //{ + // isShowResultDlg = false; + // commit(); + //} + //break; + //default: // show the result dialog after each mesh computation + //isShowResultDlg = true; + //} + + // SHOW RESULTS + if ( isShowResultDlg ) + showEvaluateResult( aRes, memoryLack, noCompError, aCompErrors, + noHypoError, aHypErrors); +} + + +void SMESHGUI_BaseComputeOp::showEvaluateResult(const SMESH::long_array& theRes, + const bool theMemoryLack, + const bool theNoCompError, + SMESH::compute_error_array_var& theCompErrors, + const bool theNoHypoError, + const QString& theHypErrors) +{ + bool hasShape = myMesh->HasShapeToMesh(); + SMESHGUI_ComputeDlg* aCompDlg = evaluateDlg(); + aCompDlg->myMemoryLackGroup->hide(); + + if ( theMemoryLack ) + { + aCompDlg->myMemoryLackGroup->show(); + aCompDlg->myFullInfo->hide(); + aCompDlg->myBriefInfo->hide(); + aCompDlg->myHypErrorGroup->hide(); + aCompDlg->myCompErrorGroup->hide(); + } + else if ( theNoCompError && theNoHypoError ) + { + aCompDlg->myFullInfo->SetMeshInfo( theRes ); + aCompDlg->myFullInfo->show(); + aCompDlg->myBriefInfo->hide(); + aCompDlg->myHypErrorGroup->hide(); + aCompDlg->myCompErrorGroup->hide(); + } + else + { + QTableWidget* tbl = aCompDlg->myTable; + aCompDlg->myBriefInfo->SetMeshInfo( theRes ); + aCompDlg->myBriefInfo->show(); + aCompDlg->myFullInfo->hide(); + + if ( theNoHypoError ) { + aCompDlg->myHypErrorGroup->hide(); + } + else { + aCompDlg->myHypErrorGroup->show(); + aCompDlg->myHypErrorLabel->setText( theHypErrors ); + } + + if ( theNoCompError ) { + aCompDlg->myCompErrorGroup->hide(); + } + else { + aCompDlg->myCompErrorGroup->show(); + + aCompDlg->myPublishBtn->hide(); + aCompDlg->myShowBtn->hide(); + + // fill table of errors + tbl->setRowCount( theCompErrors->length() ); + if ( !hasShape ) tbl->hideColumn( COL_SHAPE ); + else tbl->showColumn( COL_SHAPE ); + tbl->setColumnWidth( COL_ERROR, 200 ); + + bool hasBadMesh = false; + for ( int row = 0; row < (int) theCompErrors->length(); ++row ) + { + SMESH::ComputeError & err = theCompErrors[ row ]; + + QString text = err.algoName.in(); + if ( !tbl->item( row, COL_ALGO ) ) tbl->setItem( row, COL_ALGO, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_ALGO )->setText( text ); + + text = SMESH::errorText( err.code, err.comment.in() ); + if ( !tbl->item( row, COL_ERROR ) ) tbl->setItem( row, COL_ERROR, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_ERROR )->setText( text ); + + text = QString("%1").arg( err.subShapeID ); + if ( !tbl->item( row, COL_SHAPEID ) ) tbl->setItem( row, COL_SHAPEID, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_SHAPEID )->setText( text ); + + text = hasShape ? SMESH::shapeText( err.subShapeID, myMainShape ) : QString(""); + if ( !tbl->item( row, COL_SHAPE ) ) tbl->setItem( row, COL_SHAPE, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_SHAPE )->setText( text ); + + text = ( !hasShape || SMESH::getSubShapeSO( err.subShapeID, myMainShape )) ? "PUBLISHED" : ""; + if ( !tbl->item( row, COL_PUBLISHED ) ) tbl->setItem( row, COL_PUBLISHED, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_PUBLISHED )->setText( text ); // if text=="", "PUBLISH" button enabled + + text = err.hasBadMesh ? "hasBadMesh" : ""; + if ( !tbl->item( row, COL_BAD_MESH ) ) tbl->setItem( row, COL_BAD_MESH, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_BAD_MESH )->setText( text ); + if ( err.hasBadMesh ) hasBadMesh = true; + + //tbl->item( row, COL_ERROR )->setWordWrap( true ); // VSR: TODO ??? + tbl->resizeRowToContents( row ); + } + tbl->resizeColumnToContents( COL_ALGO ); + tbl->resizeColumnToContents( COL_SHAPE ); + tbl->setWordWrap( true ); + + if ( hasBadMesh ) + { + aCompDlg->myBadMeshBtn->show(); + aCompDlg->myBadMeshToGroupBtn->show(); + } + else + { + aCompDlg->myBadMeshBtn->hide(); + aCompDlg->myBadMeshToGroupBtn->hide(); + } + tbl->setCurrentCell(0,0); + currentCellChanged(); // to update buttons + } + } + // show dialog and wait, becase Compute can be invoked from Preview operation + //aCompDlg->exec(); // this way it becomes modal - impossible to rotate model in the Viewer + aCompDlg->show(); +} + + +//================================================================================ +/*! + * \brief Gets dialog of evaluate operation + * \retval SMESHGUI_ComputeDlg* - pointer to dialog of this operation + */ +//================================================================================ + +SMESHGUI_ComputeDlg* SMESHGUI_BaseComputeOp::evaluateDlg() const +{ + if ( !myCompDlg ) + { + SMESHGUI_BaseComputeOp* me = (SMESHGUI_BaseComputeOp*)this; + me->myCompDlg = new SMESHGUI_ComputeDlg( desktop(), true ); + // connect signals and slots + connect(myCompDlg->myShowBtn, SIGNAL (clicked()), SLOT(onPreviewShape())); + connect(myCompDlg->myPublishBtn, SIGNAL (clicked()), SLOT(onPublishShape())); + connect(myCompDlg->myBadMeshBtn, SIGNAL (clicked()), SLOT(onShowBadMesh())); + QTableWidget* aTable = me->table(); + connect(aTable, SIGNAL(itemSelectionChanged()), SLOT(currentCellChanged())); + connect(aTable, SIGNAL(currentCellChanged(int,int,int,int)), SLOT(currentCellChanged())); + } + return myCompDlg; +} +