Salome HOME
fix PAL8469. Updating the global mesh icon when local hypotheses are edited
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_HypothesesUtils.cxx
1 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
3 // 
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. 
8 // 
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. 
13 // 
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 
17 // 
18 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
19
20 #include <map>
21 #include <string>
22
23 #include <dlfcn.h>
24
25 #include "QAD.h"
26 #include "QAD_Tools.h"
27 #include "QAD_Config.h"
28 #include "QAD_Desktop.h"
29 #include "QAD_MessageBox.h"
30 #include "QAD_WaitCursor.h"
31 #include "QAD_ResourceMgr.h"
32
33 #include "SALOMEGUI_QtCatchCorbaException.hxx"
34
35 #include "SMESHGUI_HypothesesUtils.h"
36 #include "SMESHGUI_Hypotheses.h"
37 #include "SMESHGUI_XmlHandler.h"
38 #include "SMESHGUI.h"
39
40 #include "SMESHGUI_Utils.h"
41 #include "SMESHGUI_GEOMGenUtils.h"
42 #include "SMESHGUI_SMESHGenUtils.h"
43
44 #include "SALOMEconfig.h"
45 #include CORBA_CLIENT_HEADER(SALOMEDS_Attributes)
46
47 #ifdef _DEBUG_
48 static int MYDEBUG = 0;
49 #else
50 static int MYDEBUG = 0;
51 #endif
52
53 namespace SMESH{
54   
55   using namespace std;
56
57   typedef map<string,HypothesisData*> THypothesisDataMap;
58   THypothesisDataMap myHypothesesMap;
59   THypothesisDataMap myAlgorithmsMap;
60
61   typedef map<string,SMESHGUI_GenericHypothesisCreator*> THypCreatorMap;
62   THypCreatorMap myHypCreatorMap;
63
64   void addMap( const THypothesisDataMap& theMap,
65                THypothesisDataMap& toMap)
66   {
67     THypothesisDataMap::const_iterator it;
68     for ( it = theMap.begin(); it != theMap.end(); it++ )
69       toMap.insert( *it );
70   }
71
72
73   void processHypothesisStatus(const int theHypStatus,
74                                SMESH::SMESH_Hypothesis_ptr theHyp,
75                                const bool theIsAddition)
76   {
77     if ( theHypStatus > SMESH::HYP_OK ) {
78       
79       // get Hyp name
80       QString aHypName ("NULL Hypothesis");
81       if ( !CORBA::is_nil( theHyp )) {
82         SALOMEDS::SObject_var Shyp = SMESH::FindSObject( theHyp );
83         if ( !CORBA::is_nil( Shyp ))
84           // name in study
85           aHypName = Shyp->GetName();
86         else
87           // label in xml file
88           aHypName = GetHypothesisData( theHyp->GetName() )->Label;
89       }
90
91       // message
92       bool isFatal = ( theHypStatus >= SMESH::HYP_UNKNOWN_FATAL );
93       QString aMsg;
94       if ( theIsAddition )
95         aMsg = ( isFatal ? "SMESH_CANT_ADD_HYP" : "SMESH_ADD_HYP_WRN");
96       else
97         aMsg = ( isFatal ? "SMESH_CANT_RM_HYP"  : "SMESH_RM_HYP_WRN");
98       
99       aMsg = QObject::tr( aMsg ).arg( aHypName ) +
100         QObject::tr( QString( "SMESH_HYP_%1" ).arg( theHypStatus ));
101       
102       QAD_MessageBox::warn1(QAD_Application::getDesktop(),
103                             QObject::tr( "SMESH_WRN_WARNING" ),
104                             aMsg,
105                             QObject::tr( "SMESH_BUT_OK" ));
106     }
107   }
108
109
110   void InitAvailableHypotheses()
111   {
112     QAD_WaitCursor wc;
113     if (myHypothesesMap.empty() && myAlgorithmsMap.empty()) {
114       // Resource manager
115       QAD_ResourceMgr* resMgr = QAD_Desktop::createResourceManager();
116       if (!resMgr) return;
117       
118       // Find name of a resource XML file ("SMESH_Meshers.xml");
119       QString HypsXml;
120       char* cenv = getenv("SMESH_MeshersList");
121       if (cenv)
122         HypsXml.sprintf("%s", cenv);
123       
124       QStringList HypsXmlList = QStringList::split( ":", HypsXml, false );
125       if (HypsXmlList.count() == 0)
126         {
127           QAD_MessageBox::error1(QAD_Application::getDesktop(),
128                                  QObject::tr("SMESH_WRN_WARNING"),
129                                  QObject::tr("MESHERS_FILE_NO_VARIABLE"),
130                                  QObject::tr("SMESH_BUT_OK"));
131           return;
132         }
133       
134       // loop on files in HypsXml
135       QString aNoAccessFiles;
136       for ( int i = 0; i < HypsXmlList.count(); i++ ) {
137         QString HypsXml = HypsXmlList[ i ];
138         
139         // Find full path to the resource XML file
140         QString xmlFile = HypsXml + ".xml";
141         xmlFile = QAD_Tools::addSlash(resMgr->findFile(xmlFile, HypsXml)) + xmlFile;
142         
143         QFile file (QAD_Tools::unix2win(xmlFile));
144         if (file.exists() && file.open(IO_ReadOnly)) {
145           file.close();
146           
147           SMESHGUI_XmlHandler* aXmlHandler = new SMESHGUI_XmlHandler();
148           ASSERT(aXmlHandler);
149           
150           QXmlInputSource source (file);
151           QXmlSimpleReader reader;
152           reader.setContentHandler(aXmlHandler);
153           reader.setErrorHandler(aXmlHandler);
154           bool ok = reader.parse(source);
155           file.close();
156           if (ok) {
157             addMap( aXmlHandler->myHypothesesMap, myHypothesesMap );
158             addMap( aXmlHandler->myAlgorithmsMap, myAlgorithmsMap );
159           }
160           else {
161             QAD_MessageBox::error1(QAD_Application::getDesktop(), 
162                                    QObject::tr("INF_PARSE_ERROR"),
163                                    QObject::tr(aXmlHandler->errorProtocol()),
164                                    QObject::tr("SMESH_BUT_OK"));
165           }
166         }
167         else {
168           if (aNoAccessFiles.isEmpty())
169             aNoAccessFiles = xmlFile;
170           else
171             aNoAccessFiles += ", " + xmlFile;
172         }
173       } // end loop
174       
175       
176       if (!aNoAccessFiles.isEmpty()) {
177         QString aMess = QObject::tr("MESHERS_FILE_CANT_OPEN") + " " + aNoAccessFiles + "\n";
178         aMess += QObject::tr("MESHERS_FILE_CHECK_VARIABLE");
179         wc.stop();
180         QAD_MessageBox::warn1(QAD_Application::getDesktop(),
181                               QObject::tr("SMESH_WRN_WARNING"),
182                               aMess,
183                               QObject::tr("SMESH_BUT_OK"));
184         wc.start();
185       }
186     }
187   }
188
189
190   QStringList GetAvailableHypotheses(const bool isAlgo)
191   {
192     QStringList aHypList;
193     
194     // Init list of available hypotheses, if needed
195     InitAvailableHypotheses();
196     
197     // fill list of hypotheses/algorithms
198     THypothesisDataMap::iterator anIter;
199     if (isAlgo) {
200       anIter = myAlgorithmsMap.begin();
201       for (; anIter != myAlgorithmsMap.end(); anIter++) {
202         aHypList.append(((*anIter).first).c_str());
203       }
204     }
205     else {
206       anIter = myHypothesesMap.begin();
207       for (; anIter != myHypothesesMap.end(); anIter++) {
208         aHypList.append(((*anIter).first).c_str());
209       }
210     }
211     
212     return aHypList;
213   }
214   
215
216   HypothesisData* GetHypothesisData (const char* aHypType)
217   {
218     HypothesisData* aHypData = 0;
219
220     // Init list of available hypotheses, if needed
221     InitAvailableHypotheses();
222
223     if (myHypothesesMap.find(aHypType) == myHypothesesMap.end()) {
224       if (myAlgorithmsMap.find(aHypType) != myAlgorithmsMap.end()) {
225         aHypData = myAlgorithmsMap[aHypType];
226       }
227     }
228     else {
229       aHypData = myHypothesesMap[aHypType];
230     }
231     return aHypData;
232   }
233
234
235   SMESHGUI_GenericHypothesisCreator* GetHypothesisCreator(const char* aHypType)
236   {
237     if(MYDEBUG) MESSAGE("Get HypothesisCreator for " << aHypType);
238
239     SMESHGUI_GenericHypothesisCreator* aCreator = 0;
240     
241     // check, if creator for this hypothesis type already exists
242     if (myHypCreatorMap.find(aHypType) != myHypCreatorMap.end()) {
243       aCreator = myHypCreatorMap[aHypType];
244     }
245     else {
246       // 1. Init list of available hypotheses, if needed
247       InitAvailableHypotheses();
248
249       // 2. Get names of plugin libraries
250       HypothesisData* aHypData = GetHypothesisData(aHypType);
251       if (!aHypData) {
252         return aCreator;
253       }
254       QString aClientLibName = aHypData->ClientLibName;
255       QString aServerLibName = aHypData->ServerLibName;
256
257       // 3. Load Client Plugin Library
258       try {
259         // load plugin library
260         if(MYDEBUG) MESSAGE("Loading client meshers plugin library ...");
261         void* libHandle = dlopen (aClientLibName, RTLD_LAZY);
262         if (!libHandle) {
263           // report any error, if occured
264           const char* anError = dlerror();
265           if(MYDEBUG) MESSAGE(anError);
266         }
267         else {
268           // get method, returning hypothesis creator
269           if(MYDEBUG) MESSAGE("Find GetHypothesisCreator() method ...");
270           typedef SMESHGUI_GenericHypothesisCreator* (*GetHypothesisCreator) \
271             (QString aHypType, QString aServerLibName, SMESHGUI* aSMESHGUI);
272           GetHypothesisCreator procHandle =
273             (GetHypothesisCreator)dlsym( libHandle, "GetHypothesisCreator" );
274           if (!procHandle) {
275             if(MYDEBUG) MESSAGE("bad hypothesis client plugin library");
276             dlclose(libHandle);
277           }
278           else {
279             // get hypothesis creator
280             if(MYDEBUG) MESSAGE("Get Hypothesis Creator for " << aHypType);
281             aCreator = procHandle(aHypType, aServerLibName, SMESHGUI::GetSMESHGUI());
282             if (!aCreator) {
283               if(MYDEBUG) MESSAGE("no such a hypothesis in this plugin");
284             }
285             else {
286               // map hypothesis creator to a hypothesis name
287               myHypCreatorMap[aHypType] = aCreator;
288             }
289           }
290         }
291       }
292       catch (const SALOME::SALOME_Exception& S_ex) {
293         QtCatchCorbaException(S_ex);
294       }
295     }
296
297     return aCreator;
298   }
299
300
301   SMESH::SMESH_Hypothesis_ptr CreateHypothesis(const char* aHypType,
302                                                const char* aHypName,
303                                                const bool isAlgo)
304   {
305     if(MYDEBUG) MESSAGE("Create " << aHypType << " with name " << aHypName);
306
307     SMESH::SMESH_Hypothesis_var Hyp;
308     
309     HypothesisData* aHypData = GetHypothesisData(aHypType);
310     QString aServLib = aHypData->ServerLibName;
311     
312     try {
313       Hyp = SMESH::GetSMESHGen()->CreateHypothesis(aHypType, aServLib);
314       if (!Hyp->_is_nil()) {
315         SALOMEDS::SObject_var SHyp = SMESH::FindSObject(Hyp.in());
316         if (!SHyp->_is_nil()) {
317           if ( strcmp(aHypName,"") != 0 )
318             SMESH::SetName( SHyp, aHypName );
319           GetActiveStudy()->updateObjBrowser(true);
320           return Hyp._retn();
321         }
322       }
323     }
324     catch (const SALOME::SALOME_Exception & S_ex) {
325       QtCatchCorbaException(S_ex);
326     }
327
328     return SMESH::SMESH_Hypothesis::_nil();
329   }
330
331
332   bool AddHypothesisOnMesh (SMESH::SMESH_Mesh_ptr aMesh, SMESH::SMESH_Hypothesis_ptr aHyp)
333   {
334     if(MYDEBUG) MESSAGE ("SMESHGUI::AddHypothesisOnMesh");
335     int res = SMESH::HYP_UNKNOWN_FATAL; 
336     QAD_WaitCursor wc;
337     
338     if ( !aMesh->_is_nil() ) {
339       SALOMEDS::SObject_var SM = SMESH::FindSObject( aMesh );
340       GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(SM);
341       try {
342         res = aMesh->AddHypothesis( aShapeObject, aHyp );
343         if ( res < SMESH::HYP_UNKNOWN_FATAL ) {
344           SALOMEDS::SObject_var SH = SMESH::FindSObject(aHyp);
345           if ( !SM->_is_nil() && !SH->_is_nil() ) {
346             SMESH::ModifiedMesh(SM, false);
347           }
348         }
349         if ( res > SMESH::HYP_OK ) {
350           wc.stop();
351           processHypothesisStatus( res, aHyp, true );
352           wc.start();
353         }
354       }
355       catch( const SALOME::SALOME_Exception& S_ex ) {
356         wc.stop();
357         QtCatchCorbaException( S_ex );
358         res = SMESH::HYP_UNKNOWN_FATAL;
359       }
360     }
361     return res < SMESH::HYP_UNKNOWN_FATAL;
362   }
363
364
365   bool AddHypothesisOnSubMesh (SMESH::SMESH_subMesh_ptr aSubMesh, SMESH::SMESH_Hypothesis_ptr aHyp)
366   {
367     if(MYDEBUG) MESSAGE( "SMESHGUI::AddHypothesisOnSubMesh() ");
368     int res = SMESH::HYP_UNKNOWN_FATAL;
369     QAD_WaitCursor wc;
370     
371     if ( !aSubMesh->_is_nil() && ! aHyp->_is_nil() ) {
372       try {
373         SMESH::SMESH_Mesh_var aMesh = aSubMesh->GetFather();
374         SALOMEDS::SObject_var SsubM = SMESH::FindSObject( aSubMesh );
375         GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh( SsubM );
376         if ( !aMesh->_is_nil() && !SsubM->_is_nil() && !aShapeObject->_is_nil() ) {
377           res = aMesh->AddHypothesis( aShapeObject, aHyp );
378           if ( res < SMESH::HYP_UNKNOWN_FATAL )  {
379             SALOMEDS::SObject_var meshSO = SMESH::FindSObject( aMesh );
380             if ( !meshSO->_is_nil() )
381               SMESH::ModifiedMesh( meshSO, false );
382           }
383           if ( res > SMESH::HYP_OK ) {
384             wc.stop();
385             processHypothesisStatus( res, aHyp, true );
386             wc.start();
387           }
388         }
389         else {
390           SCRUTE( aHyp->_is_nil() );
391           SCRUTE( aMesh->_is_nil() );
392           SCRUTE( SsubM->_is_nil() );
393           SCRUTE( aShapeObject->_is_nil() );
394         }
395       }
396       catch( const SALOME::SALOME_Exception& S_ex ) {
397         wc.stop();
398         QtCatchCorbaException( S_ex );
399         res = SMESH::HYP_UNKNOWN_FATAL;
400       }
401     }
402     else {
403       SCRUTE( aSubMesh->_is_nil() );
404       SCRUTE( aHyp->_is_nil() );
405     }
406     return res < SMESH::HYP_UNKNOWN_FATAL;
407   }
408   
409   bool RemoveHypothesisOrAlgorithmOnMesh (const Handle(SALOME_InteractiveObject)& IObject)
410   {
411     int res = SMESH::HYP_UNKNOWN_FATAL;
412     QAD_WaitCursor wc;
413     
414     if (IObject->hasReference()) {
415       try {
416         SALOMEDS::Study_var aStudy = GetActiveStudyDocument();
417         SMESH_Hypothesis_var anHyp = IObjectToInterface<SMESH_Hypothesis>(IObject);
418         SALOMEDS::SObject_var aHypSObj = aStudy->FindObjectID(IObject->getReference());
419         if (!aHypSObj->_is_nil()) {
420           SALOMEDS::SObject_var MorSM = SMESH::GetMeshOrSubmesh(aHypSObj);
421           if (!MorSM->_is_nil()) {
422             GEOM::GEOM_Object_var aShape = SMESH::GetShapeOnMeshOrSubMesh(MorSM);
423             if (!aShape->_is_nil()){
424               SMESH::SMESH_Mesh_var aMesh = 
425                 SMESH::SObjectToInterface<SMESH::SMESH_Mesh>(MorSM);
426               SMESH::SMESH_subMesh_var aSubMesh =
427                 SMESH::SObjectToInterface<SMESH::SMESH_subMesh>(MorSM);
428               
429               if (!aSubMesh->_is_nil())
430                 aMesh = aSubMesh->GetFather();
431               
432               if (!aMesh->_is_nil()) {
433                 res = aMesh->RemoveHypothesis(aShape, anHyp);
434                 if ( res < SMESH::HYP_UNKNOWN_FATAL ) {
435                   SALOMEDS::SObject_var meshSO = SMESH::FindSObject( aMesh );
436                   if ( !meshSO->_is_nil() )
437                     SMESH::ModifiedMesh(meshSO, false);
438                 }
439                 if ( res > SMESH::HYP_OK ) {
440                   wc.stop();
441                   processHypothesisStatus( res, anHyp, false );
442                   wc.start();
443                 }
444               }
445             }
446           }
447         }
448       }
449       catch( const SALOME::SALOME_Exception& S_ex ) {
450         wc.stop();
451         QtCatchCorbaException( S_ex );
452         res = SMESH::HYP_UNKNOWN_FATAL;
453       }
454     } 
455     else if (IObject->hasEntry()) {
456       if(MYDEBUG) MESSAGE("IObject entry " << IObject->getEntry());
457     }
458     return res < SMESH::HYP_UNKNOWN_FATAL;
459   }
460   
461   bool RemoveHypothesisOrAlgorithmOnMesh (SALOMEDS::SObject_ptr MorSM,
462                                           SMESH::SMESH_Hypothesis_ptr anHyp)
463   {
464     SALOMEDS::SObject_var AHR, aRef;
465     SALOMEDS::GenericAttribute_var anAttr;
466     SALOMEDS::AttributeIOR_var anIOR;
467     int res = SMESH::HYP_UNKNOWN_FATAL;
468     QAD_WaitCursor wc;
469     
470     if (!MorSM->_is_nil()) {
471       try {
472         GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(MorSM);
473         if (!aShapeObject->_is_nil()) {
474           SMESH::SMESH_Mesh_var aMesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>(MorSM);
475           SMESH::SMESH_subMesh_var aSubMesh = SMESH::SObjectToInterface<SMESH::SMESH_subMesh>(MorSM);
476           
477           if ( !aSubMesh->_is_nil() )
478             aMesh = aSubMesh->GetFather();
479           
480           if (!aMesh->_is_nil()) {
481             res = aMesh->RemoveHypothesis(aShapeObject, anHyp);
482             if ( res < SMESH::HYP_UNKNOWN_FATAL ) {
483               SALOMEDS::SObject_var meshSO = SMESH::FindSObject( aMesh );
484               if ( !meshSO->_is_nil() )
485                 SMESH::ModifiedMesh(meshSO, false);
486             }
487             if ( res > SMESH::HYP_OK ) {
488               wc.stop();
489               processHypothesisStatus( res, anHyp, false );
490               wc.start();
491             }
492           }
493         }
494       } catch( const SALOME::SALOME_Exception& S_ex ) {
495         wc.stop();
496         QtCatchCorbaException( S_ex );
497         res = SMESH::HYP_UNKNOWN_FATAL;
498       }
499     }
500     return res < SMESH::HYP_UNKNOWN_FATAL;
501   }
502
503   SALOMEDS::Study::ListOfSObject* GetMeshesUsingAlgoOrHypothesis( SMESH::SMESH_Hypothesis_ptr AlgoOrHyp )
504   {
505     SALOMEDS::Study::ListOfSObject_var listSOmesh =
506       new SALOMEDS::Study::ListOfSObject;
507     listSOmesh->length(0);
508     unsigned int index = 0;
509     if (!AlgoOrHyp->_is_nil()) {
510       SALOMEDS::SObject_var SO_Hypothesis = SMESH::FindSObject(AlgoOrHyp);
511       if (!SO_Hypothesis->_is_nil()) {
512         SALOMEDS::Study::ListOfSObject_var listSO =
513           GetActiveStudyDocument()->FindDependances(SO_Hypothesis);
514         if(MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): dependency number ="<<listSO->length());
515         for (unsigned int i = 0; i < listSO->length(); i++) {
516           SALOMEDS::SObject_ptr SO = listSO[i];
517           if (!SO->_is_nil()) { 
518             SALOMEDS::SObject_var aFather = SO->GetFather();
519             if (!aFather->_is_nil()) {
520               SALOMEDS::SObject_var SOfatherFather = aFather->GetFather();
521               if (!SOfatherFather->_is_nil()) {
522                 if(MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): dependency added to list");
523                 index++;
524                 listSOmesh->length(index);
525                 listSOmesh[index - 1] = SOfatherFather;
526               }
527             }
528           }
529         }
530       }
531     }
532     if(MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): completed");
533     return listSOmesh._retn();
534   }
535
536 }