Salome HOME
[Bug PAL7444] display mesh takes a lot of more memory in 2.1.0 than in 2.0.0.
[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             SMESH::ModifiedMesh( SsubM, false );
380           }
381           if ( res > SMESH::HYP_OK ) {
382             wc.stop();
383             processHypothesisStatus( res, aHyp, true );
384             wc.start();
385           }
386         }
387         else {
388           SCRUTE( aHyp->_is_nil() );
389           SCRUTE( aMesh->_is_nil() );
390           SCRUTE( SsubM->_is_nil() );
391           SCRUTE( aShapeObject->_is_nil() );
392         }
393       }
394       catch( const SALOME::SALOME_Exception& S_ex ) {
395         wc.stop();
396         QtCatchCorbaException( S_ex );
397         res = SMESH::HYP_UNKNOWN_FATAL;
398       }
399     }
400     else {
401       SCRUTE( aSubMesh->_is_nil() );
402       SCRUTE( aHyp->_is_nil() );
403     }
404     return res < SMESH::HYP_UNKNOWN_FATAL;
405   }
406   
407   bool RemoveHypothesisOrAlgorithmOnMesh (const Handle(SALOME_InteractiveObject)& IObject)
408   {
409     int res = SMESH::HYP_UNKNOWN_FATAL;
410     QAD_WaitCursor wc;
411     
412     if (IObject->hasReference()) {
413       try {
414         SALOMEDS::Study_var aStudy = GetActiveStudyDocument();
415         SMESH_Hypothesis_var anHyp = IObjectToInterface<SMESH_Hypothesis>(IObject);
416         SALOMEDS::SObject_var aHypSObj = aStudy->FindObjectID(IObject->getReference());
417         if (!aHypSObj->_is_nil()) {
418           SALOMEDS::SObject_var MorSM = SMESH::GetMeshOrSubmesh(aHypSObj);
419           if (!MorSM->_is_nil()) {
420             GEOM::GEOM_Object_var aShape = SMESH::GetShapeOnMeshOrSubMesh(MorSM);
421             if (!aShape->_is_nil()){
422               SMESH::SMESH_Mesh_var aMesh = 
423                 SMESH::SObjectToInterface<SMESH::SMESH_Mesh>(MorSM);
424               SMESH::SMESH_subMesh_var aSubMesh =
425                 SMESH::SObjectToInterface<SMESH::SMESH_subMesh>(MorSM);
426               
427               if (!aSubMesh->_is_nil())
428                 aMesh = aSubMesh->GetFather();
429               
430               if (!aMesh->_is_nil()) {
431                 res = aMesh->RemoveHypothesis(aShape, anHyp);
432                 if ( res < SMESH::HYP_UNKNOWN_FATAL )
433                   SMESH::ModifiedMesh(MorSM, false);
434                 if ( res > SMESH::HYP_OK ) {
435                   wc.stop();
436                   processHypothesisStatus( res, anHyp, false );
437                   wc.start();
438                 }
439               }
440             }
441           }
442           
443           SALOMEDS::SObject_var aHypSObj = aStudy->FindObjectID(IObject->getReference());
444           if (!aHypSObj->_is_nil()) {
445             SALOMEDS::SObject_var MorSM = SMESH::GetMeshOrSubmesh(aHypSObj);
446             if (!MorSM->_is_nil()) {
447               GEOM::GEOM_Object_var aShapeObject =SMESH::GetShapeOnMeshOrSubMesh(MorSM);
448               if (!aShapeObject->_is_nil()){
449                 SMESH::SMESH_Mesh_var aMesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>(MorSM);
450                 SMESH::SMESH_subMesh_var aSubMesh = SMESH::SObjectToInterface<SMESH::SMESH_subMesh>(MorSM);
451                 
452                 if (!aSubMesh->_is_nil())
453                   aMesh = aSubMesh->GetFather();
454                 
455                 if (!aMesh->_is_nil()) {
456                   res = aMesh->RemoveHypothesis(aShapeObject, anHyp);
457                   if ( res < SMESH::HYP_UNKNOWN_FATAL )
458                     SMESH::ModifiedMesh(MorSM, false);
459                   if ( res > SMESH::HYP_OK ) {
460                     wc.stop();
461                     processHypothesisStatus( res, anHyp, false );
462                     wc.start();
463                   }
464                 }
465               }
466             }
467           }
468         }
469       }
470       catch( const SALOME::SALOME_Exception& S_ex ) {
471         wc.stop();
472         QtCatchCorbaException( S_ex );
473         res = SMESH::HYP_UNKNOWN_FATAL;
474       }
475     } 
476     else if (IObject->hasEntry()) {
477       if(MYDEBUG) MESSAGE("IObject entry " << IObject->getEntry());
478     }
479     return res < SMESH::HYP_UNKNOWN_FATAL;
480   }
481   
482   bool RemoveHypothesisOrAlgorithmOnMesh (SALOMEDS::SObject_ptr MorSM,
483                                           SMESH::SMESH_Hypothesis_ptr anHyp)
484   {
485     SALOMEDS::SObject_var AHR, aRef;
486     SALOMEDS::GenericAttribute_var anAttr;
487     SALOMEDS::AttributeIOR_var anIOR;
488     int res = SMESH::HYP_UNKNOWN_FATAL;
489     QAD_WaitCursor wc;
490     
491     if (!MorSM->_is_nil()) {
492       try {
493         GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(MorSM);
494         if (!aShapeObject->_is_nil()) {
495           SMESH::SMESH_Mesh_var aMesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>(MorSM);
496           SMESH::SMESH_subMesh_var aSubMesh = SMESH::SObjectToInterface<SMESH::SMESH_subMesh>(MorSM);
497           
498           if ( !aSubMesh->_is_nil() )
499             aMesh = aSubMesh->GetFather();
500           
501           if (!aMesh->_is_nil()) {
502             res = aMesh->RemoveHypothesis(aShapeObject, anHyp);
503             if ( res < SMESH::HYP_UNKNOWN_FATAL )
504               SMESH::ModifiedMesh(MorSM, false);
505             if ( res > SMESH::HYP_OK ) {
506               wc.stop();
507               processHypothesisStatus( res, anHyp, false );
508               wc.start();
509             }
510           }
511         }
512       } catch( const SALOME::SALOME_Exception& S_ex ) {
513         wc.stop();
514         QtCatchCorbaException( S_ex );
515         res = SMESH::HYP_UNKNOWN_FATAL;
516       }
517     }
518     return res < SMESH::HYP_UNKNOWN_FATAL;
519   }
520
521   SALOMEDS::Study::ListOfSObject* GetMeshesUsingAlgoOrHypothesis( SMESH::SMESH_Hypothesis_ptr AlgoOrHyp )
522   {
523     SALOMEDS::Study::ListOfSObject_var listSOmesh =
524       new SALOMEDS::Study::ListOfSObject;
525     listSOmesh->length(0);
526     unsigned int index = 0;
527     if (!AlgoOrHyp->_is_nil()) {
528       SALOMEDS::SObject_var SO_Hypothesis = SMESH::FindSObject(AlgoOrHyp);
529       if (!SO_Hypothesis->_is_nil()) {
530         SALOMEDS::Study::ListOfSObject_var listSO =
531           GetActiveStudyDocument()->FindDependances(SO_Hypothesis);
532         if(MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): dependency number ="<<listSO->length());
533         for (unsigned int i = 0; i < listSO->length(); i++) {
534           SALOMEDS::SObject_ptr SO = listSO[i];
535           if (!SO->_is_nil()) { 
536             SALOMEDS::SObject_var aFather = SO->GetFather();
537             if (!aFather->_is_nil()) {
538               SALOMEDS::SObject_var SOfatherFather = aFather->GetFather();
539               if (!SOfatherFather->_is_nil()) {
540                 if(MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): dependency added to list");
541                 index++;
542                 listSOmesh->length(index);
543                 listSOmesh[index - 1] = SOfatherFather;
544               }
545             }
546           }
547         }
548       }
549     }
550     if(MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): completed");
551     return listSOmesh._retn();
552   }
553
554 }