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 #include "SMESHGUI_HypothesesUtils.h"
25 #include "SMESHGUI_Hypotheses.h"
26 #include "SMESHGUI_XmlHandler.h"
27 #include "SMESHGUI_Utils.h"
28 #include "SMESHGUI_GEOMGenUtils.h"
30 #include "SUIT_Tools.h"
31 #include "SUIT_Desktop.h"
32 #include "SUIT_MessageBox.h"
33 #include "SUIT_OverrideCursor.h"
34 #include "SUIT_ResourceMgr.h"
35 #include "SUIT_Session.h"
37 #include "OB_Browser.h"
39 #include "SalomeApp_Study.h"
40 #include "SalomeApp_Tools.h"
41 #include "SalomeApp_Application.h"
43 #include <SALOMEDSClient_Study.hxx>
44 #include <SALOMEDSClient_SObject.hxx>
46 #include "SALOMEconfig.h"
47 #include CORBA_CLIENT_HEADER(SALOMEDS_Attributes)
59 #define LibHandle HMODULE
60 #define LoadLib( name ) LoadLibrary( name )
61 #define GetProc GetProcAddress
62 #define UnLoadLib( handle ) FreeLibrary( handle );
64 #define LibHandle void*
65 #define LoadLib( name ) dlopen( name, RTLD_LAZY )
67 #define UnLoadLib( handle ) dlclose( handle );
71 static int MYDEBUG = 0;
73 static int MYDEBUG = 0;
80 typedef map<string,HypothesisData*> THypothesisDataMap;
81 THypothesisDataMap myHypothesesMap;
82 THypothesisDataMap myAlgorithmsMap;
84 typedef map<string,SMESHGUI_GenericHypothesisCreator*> THypCreatorMap;
85 THypCreatorMap myHypCreatorMap;
87 list<HypothesesSet*> myListOfHypothesesSets;
89 void processHypothesisStatus(const int theHypStatus,
90 SMESH::SMESH_Hypothesis_ptr theHyp,
91 const bool theIsAddition)
93 if (theHypStatus > SMESH::HYP_OK) {
96 QString aHypName ("NULL Hypothesis");
97 if (!CORBA::is_nil(theHyp)) {
98 _PTR(SObject) Shyp = SMESH::FindSObject(theHyp);
101 aHypName = Shyp->GetName().c_str();
104 aHypName = GetHypothesisData(theHyp->GetName())->Label;
108 bool isFatal = (theHypStatus >= SMESH::HYP_UNKNOWN_FATAL);
111 aMsg = (isFatal ? "SMESH_CANT_ADD_HYP" : "SMESH_ADD_HYP_WRN");
113 aMsg = (isFatal ? "SMESH_CANT_RM_HYP" : "SMESH_RM_HYP_WRN");
115 aMsg = QObject::tr(aMsg).arg(aHypName) +
116 QObject::tr(QString("SMESH_HYP_%1").arg(theHypStatus));
118 if ( theHypStatus == SMESH::HYP_HIDDEN_ALGO ) // PAL18501
119 aMsg = aMsg.arg( GetHypothesisData(theHyp->GetName())->Dim[0] );
121 SUIT_MessageBox::warn1(SMESHGUI::desktop(),
122 QObject::tr("SMESH_WRN_WARNING"),
124 QObject::tr("SMESH_BUT_OK"));
129 void InitAvailableHypotheses()
131 SUIT_OverrideCursor wc;
132 if (myHypothesesMap.empty() && myAlgorithmsMap.empty()) {
134 SUIT_ResourceMgr* resMgr = SMESHGUI::resourceMgr();
137 // Find name of a resource XML file ("SMESH_Meshers.xml");
139 char* cenv = getenv("SMESH_MeshersList");
141 HypsXml.sprintf("%s", cenv);
143 QStringList HypsXmlList = QStringList::split(":", HypsXml, false);
144 if (HypsXmlList.count() == 0)
146 SUIT_MessageBox::error1(SMESHGUI::desktop(),
147 QObject::tr("SMESH_WRN_WARNING"),
148 QObject::tr("MESHERS_FILE_NO_VARIABLE"),
149 QObject::tr("SMESH_BUT_OK"));
153 // loop on files in HypsXml
154 QString aNoAccessFiles;
155 for (int i = 0; i < HypsXmlList.count(); i++) {
156 QString HypsXml = HypsXmlList[ i ];
158 // Find full path to the resource XML file
159 QString xmlFile = resMgr->path("resources", "SMESH", HypsXml + ".xml");
160 if ( xmlFile.isEmpty() ) // try PLUGIN resources
161 xmlFile = resMgr->path("resources", HypsXml, HypsXml + ".xml");
163 QFile file (xmlFile);
164 if (file.exists() && file.open(IO_ReadOnly)) {
167 SMESHGUI_XmlHandler* aXmlHandler = new SMESHGUI_XmlHandler();
170 QXmlInputSource source (file);
171 QXmlSimpleReader reader;
172 reader.setContentHandler(aXmlHandler);
173 reader.setErrorHandler(aXmlHandler);
174 bool ok = reader.parse(source);
177 myHypothesesMap.insert( aXmlHandler->myHypothesesMap.begin(),
178 aXmlHandler->myHypothesesMap.end() );
179 myAlgorithmsMap.insert( aXmlHandler->myAlgorithmsMap.begin(),
180 aXmlHandler->myAlgorithmsMap.end() );
181 myListOfHypothesesSets.splice( myListOfHypothesesSets.begin(),
182 aXmlHandler->myListOfHypothesesSets );
185 SUIT_MessageBox::error1(SMESHGUI::desktop(),
186 QObject::tr("INF_PARSE_ERROR"),
187 QObject::tr(aXmlHandler->errorProtocol()),
188 QObject::tr("SMESH_BUT_OK"));
192 if (aNoAccessFiles.isEmpty())
193 aNoAccessFiles = xmlFile;
195 aNoAccessFiles += ", " + xmlFile;
200 if (!aNoAccessFiles.isEmpty()) {
201 QString aMess = QObject::tr("MESHERS_FILE_CANT_OPEN") + " " + aNoAccessFiles + "\n";
202 aMess += QObject::tr("MESHERS_FILE_CHECK_VARIABLE");
204 SUIT_MessageBox::warn1(SMESHGUI::desktop(),
205 QObject::tr("SMESH_WRN_WARNING"),
207 QObject::tr("SMESH_BUT_OK"));
214 QStringList GetAvailableHypotheses( const bool isAlgo,
217 const bool isNeedGeometry)
219 QStringList aHypList;
221 // Init list of available hypotheses, if needed
222 InitAvailableHypotheses();
223 bool checkGeometry = ( !isNeedGeometry && isAlgo );
224 // fill list of hypotheses/algorithms
225 THypothesisDataMap* pMap = isAlgo ? &myAlgorithmsMap : &myHypothesesMap;
226 THypothesisDataMap::iterator anIter;
227 for ( anIter = pMap->begin(); anIter != pMap->end(); anIter++ )
229 HypothesisData* aData = (*anIter).second;
230 if ( ( theDim < 0 || aData->Dim.contains( theDim ) ) && aData->IsAux == isAux)
232 if (aData->IsNeedGeometry == isNeedGeometry)
233 aHypList.append(((*anIter).first).c_str());
236 aHypList.append(((*anIter).first).c_str());
242 QStringList GetHypothesesSets()
244 QStringList aSetNameList;
246 // Init list of available hypotheses, if needed
247 InitAvailableHypotheses();
249 list<HypothesesSet*>::iterator hypoSet = myListOfHypothesesSets.begin();
250 for ( ; hypoSet != myListOfHypothesesSets.end(); ++hypoSet )
252 HypothesesSet* aSet = *hypoSet;
253 if ( aSet && aSet->AlgoList.count() ) {
254 aSetNameList.append( aSet->HypoSetName );
261 HypothesesSet* GetHypothesesSet(const QString theSetName)
263 list<HypothesesSet*>::iterator hypoSet = myListOfHypothesesSets.begin();
264 for ( ; hypoSet != myListOfHypothesesSets.end(); ++hypoSet )
266 HypothesesSet* aSet = *hypoSet;
267 if ( aSet && aSet->HypoSetName == theSetName )
273 HypothesisData* GetHypothesisData (const char* aHypType)
275 HypothesisData* aHypData = 0;
277 // Init list of available hypotheses, if needed
278 InitAvailableHypotheses();
280 THypothesisDataMap::iterator type_data = myHypothesesMap.find(aHypType);
281 if (type_data != myHypothesesMap.end()) {
282 aHypData = type_data->second;
285 type_data = myAlgorithmsMap.find(aHypType);
286 if (type_data != myAlgorithmsMap.end())
287 aHypData = type_data->second;
292 bool IsAvailableHypothesis(const HypothesisData* algoData,
293 const QString& hypType,
299 if ( algoData->NeededHypos.contains( hypType ))
301 if ( algoData->OptionalHypos.contains( hypType)) {
308 bool IsCompatibleAlgorithm(const HypothesisData* algo1Data,
309 const HypothesisData* algo2Data)
311 if ( !algo1Data || !algo2Data )
313 const HypothesisData* algoIn = algo1Data, *algoMain = algo2Data;
314 if ( algoIn->Dim.first() > algoMain->Dim.first() ) {
315 algoIn = algo2Data; algoMain = algo1Data;
317 // look for any output type of algoIn between input types of algoMain
318 QStringList::const_iterator inElemType = algoIn->OutputTypes.begin();
319 for ( ; inElemType != algoIn->OutputTypes.end(); ++inElemType )
320 if ( algoMain->InputTypes.contains( *inElemType ))
325 SMESHGUI_GenericHypothesisCreator* GetHypothesisCreator(const char* aHypType)
327 if(MYDEBUG) MESSAGE("Get HypothesisCreator for " << aHypType);
329 SMESHGUI_GenericHypothesisCreator* aCreator = 0;
331 // check, if creator for this hypothesis type already exists
332 if (myHypCreatorMap.find(aHypType) != myHypCreatorMap.end()) {
333 aCreator = myHypCreatorMap[aHypType];
336 // 1. Init list of available hypotheses, if needed
337 InitAvailableHypotheses();
339 // 2. Get names of plugin libraries
340 HypothesisData* aHypData = GetHypothesisData(aHypType);
343 QString aClientLibName = aHypData->ClientLibName;
344 QString aServerLibName = aHypData->ServerLibName;
346 // 3. Load Client Plugin Library
348 // load plugin library
349 if(MYDEBUG) MESSAGE("Loading client meshers plugin library ...");
350 LibHandle libHandle = LoadLib( aClientLibName );
352 // report any error, if occured
356 const char* anError = "Can't load client meshers plugin library";
358 const char* anError = dlerror();
364 // get method, returning hypothesis creator
365 if(MYDEBUG) MESSAGE("Find GetHypothesisCreator() method ...");
366 typedef SMESHGUI_GenericHypothesisCreator* (*GetHypothesisCreator) \
368 GetHypothesisCreator procHandle =
369 (GetHypothesisCreator)GetProc(libHandle, "GetHypothesisCreator");
371 if(MYDEBUG) MESSAGE("bad hypothesis client plugin library");
372 UnLoadLib(libHandle);
375 // get hypothesis creator
376 if(MYDEBUG) MESSAGE("Get Hypothesis Creator for " << aHypType);
377 aCreator = procHandle( aHypType );
379 if(MYDEBUG) MESSAGE("no such a hypothesis in this plugin");
382 // map hypothesis creator to a hypothesis name
383 myHypCreatorMap[aHypType] = aCreator;
388 catch (const SALOME::SALOME_Exception& S_ex) {
389 SalomeApp_Tools::QtCatchCorbaException(S_ex);
397 SMESH::SMESH_Hypothesis_ptr CreateHypothesis(const char* aHypType,
398 const char* aHypName,
401 if(MYDEBUG) MESSAGE("Create " << aHypType << " with name " << aHypName);
402 HypothesisData* aHypData = GetHypothesisData(aHypType);
403 QString aServLib = aHypData->ServerLibName;
405 SMESH::SMESH_Hypothesis_var aHypothesis;
406 aHypothesis = SMESHGUI::GetSMESHGen()->CreateHypothesis(aHypType, aServLib);
407 if (!aHypothesis->_is_nil()) {
408 _PTR(SObject) aHypSObject = SMESH::FindSObject(aHypothesis.in());
410 if (strlen(aHypName) > 0)
411 SMESH::SetName(aHypSObject, aHypName);
412 SMESHGUI::GetSMESHGUI()->updateObjBrowser();
413 return aHypothesis._retn();
416 } catch (const SALOME::SALOME_Exception & S_ex) {
417 SalomeApp_Tools::QtCatchCorbaException(S_ex);
420 return SMESH::SMESH_Hypothesis::_nil();
424 bool AddHypothesisOnMesh (SMESH::SMESH_Mesh_ptr aMesh, SMESH::SMESH_Hypothesis_ptr aHyp)
426 if(MYDEBUG) MESSAGE ("SMESHGUI::AddHypothesisOnMesh");
427 int res = SMESH::HYP_UNKNOWN_FATAL;
428 SUIT_OverrideCursor wc;
430 if (!aMesh->_is_nil()) {
431 _PTR(SObject) SM = SMESH::FindSObject(aMesh);
432 GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(SM);
434 res = aMesh->AddHypothesis(aShapeObject, aHyp);
435 if (res < SMESH::HYP_UNKNOWN_FATAL) {
436 _PTR(SObject) aSH = SMESH::FindSObject(aHyp);
438 SMESH::ModifiedMesh(SM, false, aMesh->NbNodes()==0);
441 if (res > SMESH::HYP_OK) {
443 processHypothesisStatus(res, aHyp, true);
447 catch(const SALOME::SALOME_Exception& S_ex) {
449 SalomeApp_Tools::QtCatchCorbaException(S_ex);
450 res = SMESH::HYP_UNKNOWN_FATAL;
453 return res < SMESH::HYP_UNKNOWN_FATAL;
457 bool AddHypothesisOnSubMesh (SMESH::SMESH_subMesh_ptr aSubMesh, SMESH::SMESH_Hypothesis_ptr aHyp)
459 if(MYDEBUG) MESSAGE("SMESHGUI::AddHypothesisOnSubMesh() ");
460 int res = SMESH::HYP_UNKNOWN_FATAL;
461 SUIT_OverrideCursor wc;
463 if (!aSubMesh->_is_nil() && ! aHyp->_is_nil()) {
465 SMESH::SMESH_Mesh_var aMesh = aSubMesh->GetFather();
466 _PTR(SObject) SsubM = SMESH::FindSObject(aSubMesh);
467 GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(SsubM);
468 if (!aMesh->_is_nil() && SsubM && !aShapeObject->_is_nil()) {
469 res = aMesh->AddHypothesis(aShapeObject, aHyp);
470 if (res < SMESH::HYP_UNKNOWN_FATAL) {
471 _PTR(SObject) meshSO = SMESH::FindSObject(aMesh);
473 SMESH::ModifiedMesh(meshSO, false, aMesh->NbNodes()==0);
475 if (res > SMESH::HYP_OK) {
477 processHypothesisStatus(res, aHyp, true);
482 SCRUTE(aHyp->_is_nil());
483 SCRUTE(aMesh->_is_nil());
485 SCRUTE(aShapeObject->_is_nil());
488 catch(const SALOME::SALOME_Exception& S_ex) {
490 SalomeApp_Tools::QtCatchCorbaException(S_ex);
491 res = SMESH::HYP_UNKNOWN_FATAL;
495 SCRUTE(aSubMesh->_is_nil());
496 SCRUTE(aHyp->_is_nil());
498 return res < SMESH::HYP_UNKNOWN_FATAL;
501 bool RemoveHypothesisOrAlgorithmOnMesh (const Handle(SALOME_InteractiveObject)& IObject)
503 int res = SMESH::HYP_UNKNOWN_FATAL;
504 SUIT_OverrideCursor wc;
507 _PTR(Study) aStudy = GetActiveStudyDocument();
508 _PTR(SObject) aHypObj = aStudy->FindObjectID( IObject->getEntry() );
511 _PTR(SObject) MorSM = SMESH::GetMeshOrSubmesh( aHypObj );
512 _PTR(SObject) aRealHypo;
513 if( aHypObj->ReferencedObject( aRealHypo ) )
515 SMESH_Hypothesis_var hypo = SMESH_Hypothesis::_narrow( SObjectToObject( aRealHypo ) );
516 RemoveHypothesisOrAlgorithmOnMesh( MorSM, hypo );
520 SMESH_Hypothesis_var hypo = SMESH_Hypothesis::_narrow( SObjectToObject( aHypObj ) );
521 SObjectList meshList = GetMeshesUsingAlgoOrHypothesis( hypo );
522 for( int i = 0; i < meshList.size(); i++ )
523 RemoveHypothesisOrAlgorithmOnMesh( meshList[ i ], hypo );
527 catch(const SALOME::SALOME_Exception& S_ex)
530 SalomeApp_Tools::QtCatchCorbaException(S_ex);
531 res = SMESH::HYP_UNKNOWN_FATAL;
533 return res < SMESH::HYP_UNKNOWN_FATAL;
536 bool RemoveHypothesisOrAlgorithmOnMesh (_PTR(SObject) MorSM,
537 SMESH::SMESH_Hypothesis_ptr anHyp)
539 SALOMEDS::GenericAttribute_var anAttr;
540 SALOMEDS::AttributeIOR_var anIOR;
541 int res = SMESH::HYP_UNKNOWN_FATAL;
542 SUIT_OverrideCursor wc;
546 GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(MorSM);
547 SMESH::SMESH_Mesh_var aMesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>(MorSM);
548 SMESH::SMESH_subMesh_var aSubMesh = SMESH::SObjectToInterface<SMESH::SMESH_subMesh>(MorSM);
550 if (!aSubMesh->_is_nil())
551 aMesh = aSubMesh->GetFather();
553 if (!aMesh->_is_nil()) {
554 if (aMesh->HasShapeToMesh() && !aShapeObject->_is_nil()) {
555 res = aMesh->RemoveHypothesis(aShapeObject, anHyp);
556 if (res < SMESH::HYP_UNKNOWN_FATAL) {
557 _PTR(SObject) meshSO = SMESH::FindSObject(aMesh);
559 SMESH::ModifiedMesh(meshSO, false, aMesh->NbNodes()==0);
563 else if(!aMesh->HasShapeToMesh()){
564 res = aMesh->RemoveHypothesis(aShapeObject, anHyp);
565 if (res < SMESH::HYP_UNKNOWN_FATAL) {
566 _PTR(SObject) meshSO = SMESH::FindSObject(aMesh);
568 SMESH::ModifiedMesh(meshSO, false, aMesh->NbNodes()==0);
571 if (res > SMESH::HYP_OK) {
573 processHypothesisStatus(res, anHyp, false);
577 } catch(const SALOME::SALOME_Exception& S_ex) {
579 SalomeApp_Tools::QtCatchCorbaException(S_ex);
580 res = SMESH::HYP_UNKNOWN_FATAL;
583 return res < SMESH::HYP_UNKNOWN_FATAL;
586 SObjectList GetMeshesUsingAlgoOrHypothesis(SMESH::SMESH_Hypothesis_ptr AlgoOrHyp)
588 SObjectList listSOmesh;
589 listSOmesh.resize(0);
591 unsigned int index = 0;
592 if (!AlgoOrHyp->_is_nil()) {
593 _PTR(SObject) SO_Hypothesis = SMESH::FindSObject(AlgoOrHyp);
596 SMESHGUI::activeStudy()->studyDS()->FindDependances(SO_Hypothesis);
598 if(MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): dependency number ="<<listSO.size());
599 for (unsigned int i = 0; i < listSO.size(); i++) {
600 _PTR(SObject) SO = listSO[i];
602 _PTR(SObject) aFather = SO->GetFather();
604 _PTR(SObject) SOfatherFather = aFather->GetFather();
605 if (SOfatherFather) {
606 if(MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): dependency added to list");
608 listSOmesh.resize(index);
609 listSOmesh[index - 1] = SOfatherFather;
616 if (MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): completed");
620 #define CASE2MESSAGE(enum) case SMESH::enum: msg = QObject::tr( "STATE_" #enum ); break;
621 QString GetMessageOnAlgoStateErrors(const algo_error_array& errors)
623 QString resMsg; // PAL14861 = QObject::tr("SMESH_WRN_MISSING_PARAMETERS") + ":\n";
624 for ( int i = 0; i < errors.length(); ++i ) {
625 const SMESH::AlgoStateError & error = errors[ i ];
626 const bool hasAlgo = ( strlen( error.algoName ) != 0 );
629 msg = QObject::tr( "STATE_ALGO_MISSING" );
631 switch( error.state ) {
632 CASE2MESSAGE( HYP_MISSING );
633 CASE2MESSAGE( HYP_NOTCONFORM );
634 CASE2MESSAGE( HYP_BAD_PARAMETER );
635 CASE2MESSAGE( HYP_BAD_GEOMETRY );
638 // apply args to message:
641 msg = msg.arg( error.algoName.in() );
643 msg = msg.arg( error.algoDim );
645 msg = msg.arg( QObject::tr( error.isGlobalAlgo ? "GLOBAL_ALGO" : "LOCAL_ALGO" ));
646 // %4 - hypothesis dim == algoDim
647 msg = msg.arg( error.algoDim );
649 if ( i ) resMsg += ";\n";