1 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "SMESHGUI_HypothesesUtils.h"
23 #include "SMESHGUI_Hypotheses.h"
24 #include "SMESHGUI_XmlHandler.h"
25 #include "SMESHGUI_Utils.h"
26 #include "SMESHGUI_GEOMGenUtils.h"
28 #include "SUIT_Tools.h"
29 #include "SUIT_Desktop.h"
30 #include "SUIT_MessageBox.h"
31 #include "SUIT_OverrideCursor.h"
32 #include "SUIT_ResourceMgr.h"
33 #include "SUIT_Session.h"
35 #include "OB_Browser.h"
37 #include "SalomeApp_Study.h"
38 #include "SalomeApp_Tools.h"
39 #include "SalomeApp_Application.h"
41 #include <SALOMEDSClient_Study.hxx>
42 #include <SALOMEDSClient_SObject.hxx>
44 #include "SALOMEconfig.h"
45 #include CORBA_CLIENT_HEADER(SALOMEDS_Attributes)
53 static int MYDEBUG = 0;
55 static int MYDEBUG = 0;
62 typedef map<string,HypothesisData*> THypothesisDataMap;
63 THypothesisDataMap myHypothesesMap;
64 THypothesisDataMap myAlgorithmsMap;
66 typedef map<string,SMESHGUI_GenericHypothesisCreator*> THypCreatorMap;
67 THypCreatorMap myHypCreatorMap;
69 list<HypothesesSet*> myListOfHypothesesSets;
71 void processHypothesisStatus(const int theHypStatus,
72 SMESH::SMESH_Hypothesis_ptr theHyp,
73 const bool theIsAddition)
75 if (theHypStatus > SMESH::HYP_OK) {
78 QString aHypName ("NULL Hypothesis");
79 if (!CORBA::is_nil(theHyp)) {
80 _PTR(SObject) Shyp = SMESH::FindSObject(theHyp);
83 aHypName = Shyp->GetName().c_str();
86 aHypName = GetHypothesisData(theHyp->GetName())->Label;
90 bool isFatal = (theHypStatus >= SMESH::HYP_UNKNOWN_FATAL);
93 aMsg = (isFatal ? "SMESH_CANT_ADD_HYP" : "SMESH_ADD_HYP_WRN");
95 aMsg = (isFatal ? "SMESH_CANT_RM_HYP" : "SMESH_RM_HYP_WRN");
97 aMsg = QObject::tr(aMsg).arg(aHypName) +
98 QObject::tr(QString("SMESH_HYP_%1").arg(theHypStatus));
100 if ( theHypStatus == SMESH::HYP_HIDDEN_ALGO ) // PAL18501
101 aMsg = aMsg.arg( GetHypothesisData(theHyp->GetName())->Dim[0] );
103 SUIT_MessageBox::warn1(SMESHGUI::desktop(),
104 QObject::tr("SMESH_WRN_WARNING"),
106 QObject::tr("SMESH_BUT_OK"));
111 void InitAvailableHypotheses()
113 SUIT_OverrideCursor wc;
114 if (myHypothesesMap.empty() && myAlgorithmsMap.empty()) {
116 SUIT_ResourceMgr* resMgr = SMESHGUI::resourceMgr();
119 // Find name of a resource XML file ("SMESH_Meshers.xml");
121 char* cenv = getenv("SMESH_MeshersList");
123 HypsXml.sprintf("%s", cenv);
125 QStringList HypsXmlList = QStringList::split(":", HypsXml, false);
126 if (HypsXmlList.count() == 0)
128 SUIT_MessageBox::error1(SMESHGUI::desktop(),
129 QObject::tr("SMESH_WRN_WARNING"),
130 QObject::tr("MESHERS_FILE_NO_VARIABLE"),
131 QObject::tr("SMESH_BUT_OK"));
135 // loop on files in HypsXml
136 QString aNoAccessFiles;
137 for (int i = 0; i < HypsXmlList.count(); i++) {
138 QString HypsXml = HypsXmlList[ i ];
140 // Find full path to the resource XML file
141 QString xmlFile = resMgr->path("resources", "SMESH", HypsXml + ".xml");
142 if ( xmlFile.isEmpty() ) // try PLUGIN resources
143 xmlFile = resMgr->path("resources", HypsXml, HypsXml + ".xml");
145 QFile file (xmlFile);
146 if (file.exists() && file.open(IO_ReadOnly)) {
149 SMESHGUI_XmlHandler* aXmlHandler = new SMESHGUI_XmlHandler();
152 QXmlInputSource source (file);
153 QXmlSimpleReader reader;
154 reader.setContentHandler(aXmlHandler);
155 reader.setErrorHandler(aXmlHandler);
156 bool ok = reader.parse(source);
159 myHypothesesMap.insert( aXmlHandler->myHypothesesMap.begin(),
160 aXmlHandler->myHypothesesMap.end() );
161 myAlgorithmsMap.insert( aXmlHandler->myAlgorithmsMap.begin(),
162 aXmlHandler->myAlgorithmsMap.end() );
163 myListOfHypothesesSets.splice( myListOfHypothesesSets.begin(),
164 aXmlHandler->myListOfHypothesesSets );
167 SUIT_MessageBox::error1(SMESHGUI::desktop(),
168 QObject::tr("INF_PARSE_ERROR"),
169 QObject::tr(aXmlHandler->errorProtocol()),
170 QObject::tr("SMESH_BUT_OK"));
174 if (aNoAccessFiles.isEmpty())
175 aNoAccessFiles = xmlFile;
177 aNoAccessFiles += ", " + xmlFile;
182 if (!aNoAccessFiles.isEmpty()) {
183 QString aMess = QObject::tr("MESHERS_FILE_CANT_OPEN") + " " + aNoAccessFiles + "\n";
184 aMess += QObject::tr("MESHERS_FILE_CHECK_VARIABLE");
186 SUIT_MessageBox::warn1(SMESHGUI::desktop(),
187 QObject::tr("SMESH_WRN_WARNING"),
189 QObject::tr("SMESH_BUT_OK"));
196 QStringList GetAvailableHypotheses( const bool isAlgo,
200 QStringList aHypList;
202 // Init list of available hypotheses, if needed
203 InitAvailableHypotheses();
205 // fill list of hypotheses/algorithms
206 THypothesisDataMap* pMap = isAlgo ? &myAlgorithmsMap : &myHypothesesMap;
207 THypothesisDataMap::iterator anIter;
208 for ( anIter = pMap->begin(); anIter != pMap->end(); anIter++ )
210 HypothesisData* aData = (*anIter).second;
211 if ( ( theDim < 0 || aData->Dim.contains( theDim ) ) && aData->IsAux == isAux )
212 aHypList.append(((*anIter).first).c_str());
218 QStringList GetHypothesesSets()
220 QStringList aSetNameList;
222 // Init list of available hypotheses, if needed
223 InitAvailableHypotheses();
225 list<HypothesesSet*>::iterator hypoSet = myListOfHypothesesSets.begin();
226 for ( ; hypoSet != myListOfHypothesesSets.end(); ++hypoSet )
228 HypothesesSet* aSet = *hypoSet;
229 if ( aSet && aSet->AlgoList.count() ) {
230 aSetNameList.append( aSet->HypoSetName );
237 HypothesesSet* GetHypothesesSet(const QString theSetName)
239 list<HypothesesSet*>::iterator hypoSet = myListOfHypothesesSets.begin();
240 for ( ; hypoSet != myListOfHypothesesSets.end(); ++hypoSet )
242 HypothesesSet* aSet = *hypoSet;
243 if ( aSet && aSet->HypoSetName == theSetName )
249 HypothesisData* GetHypothesisData (const char* aHypType)
251 HypothesisData* aHypData = 0;
253 // Init list of available hypotheses, if needed
254 InitAvailableHypotheses();
256 THypothesisDataMap::iterator type_data = myHypothesesMap.find(aHypType);
257 if (type_data != myHypothesesMap.end()) {
258 aHypData = type_data->second;
261 type_data = myAlgorithmsMap.find(aHypType);
262 if (type_data != myAlgorithmsMap.end())
263 aHypData = type_data->second;
268 bool IsAvailableHypothesis(const HypothesisData* algoData,
269 const QString& hypType,
275 if ( algoData->NeededHypos.contains( hypType ))
277 if ( algoData->OptionalHypos.contains( hypType)) {
284 bool IsCompatibleAlgorithm(const HypothesisData* algo1Data,
285 const HypothesisData* algo2Data)
287 if ( !algo1Data || !algo2Data )
289 const HypothesisData* algoIn = algo1Data, *algoMain = algo2Data;
290 if ( algoIn->Dim.first() > algoMain->Dim.first() ) {
291 algoIn = algo2Data; algoMain = algo1Data;
293 // look for any output type of algoIn between input types of algoMain
294 QStringList::const_iterator inElemType = algoIn->OutputTypes.begin();
295 for ( ; inElemType != algoIn->OutputTypes.end(); ++inElemType )
296 if ( algoMain->InputTypes.contains( *inElemType ))
301 SMESHGUI_GenericHypothesisCreator* GetHypothesisCreator(const char* aHypType)
303 if(MYDEBUG) MESSAGE("Get HypothesisCreator for " << aHypType);
305 SMESHGUI_GenericHypothesisCreator* aCreator = 0;
307 // check, if creator for this hypothesis type already exists
308 if (myHypCreatorMap.find(aHypType) != myHypCreatorMap.end()) {
309 aCreator = myHypCreatorMap[aHypType];
312 // 1. Init list of available hypotheses, if needed
313 InitAvailableHypotheses();
315 // 2. Get names of plugin libraries
316 HypothesisData* aHypData = GetHypothesisData(aHypType);
319 QString aClientLibName = aHypData->ClientLibName;
320 QString aServerLibName = aHypData->ServerLibName;
322 // 3. Load Client Plugin Library
324 // load plugin library
325 if(MYDEBUG) MESSAGE("Loading client meshers plugin library ...");
326 void* libHandle = dlopen (aClientLibName, RTLD_LAZY);
328 // report any error, if occured
329 const char* anError = dlerror();
333 // get method, returning hypothesis creator
334 if(MYDEBUG) MESSAGE("Find GetHypothesisCreator() method ...");
335 typedef SMESHGUI_GenericHypothesisCreator* (*GetHypothesisCreator) \
337 GetHypothesisCreator procHandle =
338 (GetHypothesisCreator)dlsym(libHandle, "GetHypothesisCreator");
340 if(MYDEBUG) MESSAGE("bad hypothesis client plugin library");
344 // get hypothesis creator
345 if(MYDEBUG) MESSAGE("Get Hypothesis Creator for " << aHypType);
346 aCreator = procHandle( aHypType );
348 if(MYDEBUG) MESSAGE("no such a hypothesis in this plugin");
351 // map hypothesis creator to a hypothesis name
352 myHypCreatorMap[aHypType] = aCreator;
357 catch (const SALOME::SALOME_Exception& S_ex) {
358 SalomeApp_Tools::QtCatchCorbaException(S_ex);
366 SMESH::SMESH_Hypothesis_ptr CreateHypothesis(const char* aHypType,
367 const char* aHypName,
370 if(MYDEBUG) MESSAGE("Create " << aHypType << " with name " << aHypName);
371 HypothesisData* aHypData = GetHypothesisData(aHypType);
372 QString aServLib = aHypData->ServerLibName;
374 SMESH::SMESH_Hypothesis_var aHypothesis;
375 aHypothesis = SMESHGUI::GetSMESHGen()->CreateHypothesis(aHypType, aServLib);
376 if (!aHypothesis->_is_nil()) {
377 _PTR(SObject) aHypSObject = SMESH::FindSObject(aHypothesis.in());
379 if (strlen(aHypName) > 0)
380 SMESH::SetName(aHypSObject, aHypName);
381 SMESHGUI::GetSMESHGUI()->updateObjBrowser();
382 return aHypothesis._retn();
385 } catch (const SALOME::SALOME_Exception & S_ex) {
386 SalomeApp_Tools::QtCatchCorbaException(S_ex);
389 return SMESH::SMESH_Hypothesis::_nil();
393 bool AddHypothesisOnMesh (SMESH::SMESH_Mesh_ptr aMesh, SMESH::SMESH_Hypothesis_ptr aHyp)
395 if(MYDEBUG) MESSAGE ("SMESHGUI::AddHypothesisOnMesh");
396 int res = SMESH::HYP_UNKNOWN_FATAL;
397 SUIT_OverrideCursor wc;
399 if (!aMesh->_is_nil()) {
400 _PTR(SObject) SM = SMESH::FindSObject(aMesh);
401 GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(SM);
403 res = aMesh->AddHypothesis(aShapeObject, aHyp);
404 if (res < SMESH::HYP_UNKNOWN_FATAL) {
405 _PTR(SObject) aSH = SMESH::FindSObject(aHyp);
407 SMESH::ModifiedMesh(SM, false, aMesh->NbNodes()==0);
410 if (res > SMESH::HYP_OK) {
412 processHypothesisStatus(res, aHyp, true);
416 catch(const SALOME::SALOME_Exception& S_ex) {
418 SalomeApp_Tools::QtCatchCorbaException(S_ex);
419 res = SMESH::HYP_UNKNOWN_FATAL;
422 return res < SMESH::HYP_UNKNOWN_FATAL;
426 bool AddHypothesisOnSubMesh (SMESH::SMESH_subMesh_ptr aSubMesh, SMESH::SMESH_Hypothesis_ptr aHyp)
428 if(MYDEBUG) MESSAGE("SMESHGUI::AddHypothesisOnSubMesh() ");
429 int res = SMESH::HYP_UNKNOWN_FATAL;
430 SUIT_OverrideCursor wc;
432 if (!aSubMesh->_is_nil() && ! aHyp->_is_nil()) {
434 SMESH::SMESH_Mesh_var aMesh = aSubMesh->GetFather();
435 _PTR(SObject) SsubM = SMESH::FindSObject(aSubMesh);
436 GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(SsubM);
437 if (!aMesh->_is_nil() && SsubM && !aShapeObject->_is_nil()) {
438 res = aMesh->AddHypothesis(aShapeObject, aHyp);
439 if (res < SMESH::HYP_UNKNOWN_FATAL) {
440 _PTR(SObject) meshSO = SMESH::FindSObject(aMesh);
442 SMESH::ModifiedMesh(meshSO, false, aMesh->NbNodes()==0);
444 if (res > SMESH::HYP_OK) {
446 processHypothesisStatus(res, aHyp, true);
451 SCRUTE(aHyp->_is_nil());
452 SCRUTE(aMesh->_is_nil());
454 SCRUTE(aShapeObject->_is_nil());
457 catch(const SALOME::SALOME_Exception& S_ex) {
459 SalomeApp_Tools::QtCatchCorbaException(S_ex);
460 res = SMESH::HYP_UNKNOWN_FATAL;
464 SCRUTE(aSubMesh->_is_nil());
465 SCRUTE(aHyp->_is_nil());
467 return res < SMESH::HYP_UNKNOWN_FATAL;
470 bool RemoveHypothesisOrAlgorithmOnMesh (const Handle(SALOME_InteractiveObject)& IObject)
472 int res = SMESH::HYP_UNKNOWN_FATAL;
473 SUIT_OverrideCursor wc;
476 _PTR(Study) aStudy = GetActiveStudyDocument();
477 _PTR(SObject) aHypObj = aStudy->FindObjectID( IObject->getEntry() );
480 _PTR(SObject) MorSM = SMESH::GetMeshOrSubmesh( aHypObj );
481 _PTR(SObject) aRealHypo;
482 if( aHypObj->ReferencedObject( aRealHypo ) )
484 SMESH_Hypothesis_var hypo = SMESH_Hypothesis::_narrow( SObjectToObject( aRealHypo ) );
485 RemoveHypothesisOrAlgorithmOnMesh( MorSM, hypo );
489 SMESH_Hypothesis_var hypo = SMESH_Hypothesis::_narrow( SObjectToObject( aHypObj ) );
490 SObjectList meshList = GetMeshesUsingAlgoOrHypothesis( hypo );
491 for( int i = 0; i < meshList.size(); i++ )
492 RemoveHypothesisOrAlgorithmOnMesh( meshList[ i ], hypo );
496 catch(const SALOME::SALOME_Exception& S_ex)
499 SalomeApp_Tools::QtCatchCorbaException(S_ex);
500 res = SMESH::HYP_UNKNOWN_FATAL;
502 return res < SMESH::HYP_UNKNOWN_FATAL;
505 bool RemoveHypothesisOrAlgorithmOnMesh (_PTR(SObject) MorSM,
506 SMESH::SMESH_Hypothesis_ptr anHyp)
508 SALOMEDS::GenericAttribute_var anAttr;
509 SALOMEDS::AttributeIOR_var anIOR;
510 int res = SMESH::HYP_UNKNOWN_FATAL;
511 SUIT_OverrideCursor wc;
515 GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(MorSM);
516 if (!aShapeObject->_is_nil()) {
517 SMESH::SMESH_Mesh_var aMesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>(MorSM);
518 SMESH::SMESH_subMesh_var aSubMesh = SMESH::SObjectToInterface<SMESH::SMESH_subMesh>(MorSM);
520 if (!aSubMesh->_is_nil())
521 aMesh = aSubMesh->GetFather();
523 if (!aMesh->_is_nil()) {
524 res = aMesh->RemoveHypothesis(aShapeObject, anHyp);
525 if (res < SMESH::HYP_UNKNOWN_FATAL) {
526 _PTR(SObject) meshSO = SMESH::FindSObject(aMesh);
528 SMESH::ModifiedMesh(meshSO, false, aMesh->NbNodes()==0);
530 if (res > SMESH::HYP_OK) {
532 processHypothesisStatus(res, anHyp, false);
537 } catch(const SALOME::SALOME_Exception& S_ex) {
539 SalomeApp_Tools::QtCatchCorbaException(S_ex);
540 res = SMESH::HYP_UNKNOWN_FATAL;
543 return res < SMESH::HYP_UNKNOWN_FATAL;
546 SObjectList GetMeshesUsingAlgoOrHypothesis(SMESH::SMESH_Hypothesis_ptr AlgoOrHyp)
548 SObjectList listSOmesh;
549 listSOmesh.resize(0);
551 unsigned int index = 0;
552 if (!AlgoOrHyp->_is_nil()) {
553 _PTR(SObject) SO_Hypothesis = SMESH::FindSObject(AlgoOrHyp);
556 SMESHGUI::activeStudy()->studyDS()->FindDependances(SO_Hypothesis);
558 if(MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): dependency number ="<<listSO.size());
559 for (unsigned int i = 0; i < listSO.size(); i++) {
560 _PTR(SObject) SO = listSO[i];
562 _PTR(SObject) aFather = SO->GetFather();
564 _PTR(SObject) SOfatherFather = aFather->GetFather();
565 if (SOfatherFather) {
566 if(MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): dependency added to list");
568 listSOmesh.resize(index);
569 listSOmesh[index - 1] = SOfatherFather;
576 if (MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): completed");
580 #define CASE2MESSAGE(enum) case SMESH::enum: msg = QObject::tr( "STATE_" #enum ); break;
581 QString GetMessageOnAlgoStateErrors(const algo_error_array& errors)
583 QString resMsg; // PAL14861 = QObject::tr("SMESH_WRN_MISSING_PARAMETERS") + ":\n";
584 for ( int i = 0; i < errors.length(); ++i ) {
585 const SMESH::AlgoStateError & error = errors[ i ];
586 const bool hasAlgo = ( strlen( error.algoName ) != 0 );
589 msg = QObject::tr( "STATE_ALGO_MISSING" );
591 switch( error.state ) {
592 CASE2MESSAGE( HYP_MISSING );
593 CASE2MESSAGE( HYP_NOTCONFORM );
594 CASE2MESSAGE( HYP_BAD_PARAMETER );
595 CASE2MESSAGE( HYP_BAD_GEOMETRY );
598 // apply args to message:
601 msg = msg.arg( error.algoName.in() );
603 msg = msg.arg( error.algoDim );
605 msg = msg.arg( QObject::tr( error.isGlobalAlgo ? "GLOBAL_ALGO" : "LOCAL_ALGO" ));
606 // %4 - hypothesis dim == algoDim
607 msg = msg.arg( error.algoDim );
609 if ( i ) resMsg += ";\n";