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