Salome HOME
- FitAll();
[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.salome-platform.org/ or email : webmaster.salome@opencascade.com
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 #ifdef WNT
51  #include <windows.h>
52 #else
53  #include <dlfcn.h>
54 #endif
55
56 #ifdef WNT
57  #define LibHandle HMODULE
58  #define LoadLib( name ) LoadLibrary( name )
59  #define GetProc GetProcAddress
60  #define UnLoadLib( handle ) FreeLibrary( handle );
61 #else
62  #define LibHandle void*
63  #define LoadLib( name ) dlopen( name, RTLD_LAZY )
64  #define GetProc dlsym
65  #define UnLoadLib( handle ) dlclose( handle );
66 #endif
67
68 #ifdef _DEBUG_
69 static int MYDEBUG = 0;
70 #else
71 static int MYDEBUG = 0;
72 #endif
73
74 namespace SMESH{
75
76   using namespace std;
77
78   typedef map<string,HypothesisData*> THypothesisDataMap;
79   THypothesisDataMap myHypothesesMap;
80   THypothesisDataMap myAlgorithmsMap;
81
82   typedef map<string,SMESHGUI_GenericHypothesisCreator*> THypCreatorMap;
83   THypCreatorMap myHypCreatorMap;
84
85   list<HypothesesSet*> myListOfHypothesesSets;
86
87   void processHypothesisStatus(const int theHypStatus,
88                                SMESH::SMESH_Hypothesis_ptr theHyp,
89                                const bool theIsAddition)
90   {
91     if (theHypStatus > SMESH::HYP_OK) {
92
93       // get Hyp name
94       QString aHypName ("NULL Hypothesis");
95       if (!CORBA::is_nil(theHyp)) {
96         _PTR(SObject) Shyp = SMESH::FindSObject(theHyp);
97         if (Shyp)
98           // name in study
99           aHypName = Shyp->GetName().c_str();
100         else
101           // label in xml file
102           aHypName = GetHypothesisData(theHyp->GetName())->Label;
103       }
104
105       // message
106       bool isFatal = (theHypStatus >= SMESH::HYP_UNKNOWN_FATAL);
107       QString aMsg;
108       if (theIsAddition)
109         aMsg = (isFatal ? "SMESH_CANT_ADD_HYP" : "SMESH_ADD_HYP_WRN");
110       else
111         aMsg = (isFatal ? "SMESH_CANT_RM_HYP"  : "SMESH_RM_HYP_WRN");
112
113       aMsg = QObject::tr(aMsg).arg(aHypName) +
114         QObject::tr(QString("SMESH_HYP_%1").arg(theHypStatus));
115
116       SUIT_MessageBox::warn1(SMESHGUI::desktop(),
117                             QObject::tr("SMESH_WRN_WARNING"),
118                             aMsg,
119                             QObject::tr("SMESH_BUT_OK"));
120     }
121   }
122
123
124   void InitAvailableHypotheses()
125   {
126     SUIT_OverrideCursor wc;
127     if (myHypothesesMap.empty() && myAlgorithmsMap.empty()) {
128       // Resource manager
129       SUIT_ResourceMgr* resMgr = SMESHGUI::resourceMgr();
130       if (!resMgr) return;
131
132       // Find name of a resource XML file ("SMESH_Meshers.xml");
133       QString HypsXml;
134       char* cenv = getenv("SMESH_MeshersList");
135       if (cenv)
136         HypsXml.sprintf("%s", cenv);
137
138       QStringList HypsXmlList = QStringList::split(":", HypsXml, false);
139       if (HypsXmlList.count() == 0)
140         {
141           SUIT_MessageBox::error1(SMESHGUI::desktop(),
142                                  QObject::tr("SMESH_WRN_WARNING"),
143                                  QObject::tr("MESHERS_FILE_NO_VARIABLE"),
144                                  QObject::tr("SMESH_BUT_OK"));
145           return;
146         }
147
148       // loop on files in HypsXml
149       QString aNoAccessFiles;
150       for (int i = 0; i < HypsXmlList.count(); i++) {
151         QString HypsXml = HypsXmlList[ i ];
152
153         // Find full path to the resource XML file
154         QString xmlFile = resMgr->path("resources", "SMESH", HypsXml + ".xml");
155         if ( xmlFile.isEmpty() ) // try PLUGIN resources
156           xmlFile = resMgr->path("resources", HypsXml, HypsXml + ".xml");
157         
158         QFile file (xmlFile);
159         if (file.exists() && file.open(IO_ReadOnly)) {
160           file.close();
161
162           SMESHGUI_XmlHandler* aXmlHandler = new SMESHGUI_XmlHandler();
163           ASSERT(aXmlHandler);
164
165           QXmlInputSource source (file);
166           QXmlSimpleReader reader;
167           reader.setContentHandler(aXmlHandler);
168           reader.setErrorHandler(aXmlHandler);
169           bool ok = reader.parse(source);
170           file.close();
171           if (ok) {
172             myHypothesesMap.insert( aXmlHandler->myHypothesesMap.begin(),
173                                     aXmlHandler->myHypothesesMap.end() );
174             myAlgorithmsMap.insert( aXmlHandler->myAlgorithmsMap.begin(),
175                                     aXmlHandler->myAlgorithmsMap.end() );
176             myListOfHypothesesSets.splice( myListOfHypothesesSets.begin(),
177                                            aXmlHandler->myListOfHypothesesSets );
178           }
179           else {
180             SUIT_MessageBox::error1(SMESHGUI::desktop(),
181                                    QObject::tr("INF_PARSE_ERROR"),
182                                    QObject::tr(aXmlHandler->errorProtocol()),
183                                    QObject::tr("SMESH_BUT_OK"));
184           }
185         }
186         else {
187           if (aNoAccessFiles.isEmpty())
188             aNoAccessFiles = xmlFile;
189           else
190             aNoAccessFiles += ", " + xmlFile;
191         }
192       } // end loop
193
194
195       if (!aNoAccessFiles.isEmpty()) {
196         QString aMess = QObject::tr("MESHERS_FILE_CANT_OPEN") + " " + aNoAccessFiles + "\n";
197         aMess += QObject::tr("MESHERS_FILE_CHECK_VARIABLE");
198         wc.suspend();
199         SUIT_MessageBox::warn1(SMESHGUI::desktop(),
200                               QObject::tr("SMESH_WRN_WARNING"),
201                               aMess,
202                               QObject::tr("SMESH_BUT_OK"));
203         wc.resume();
204       }
205     }
206   }
207
208
209   QStringList GetAvailableHypotheses( const bool isAlgo, 
210                                       const int theDim,                          
211                                       const bool isAux )
212   {
213     QStringList aHypList;
214
215     // Init list of available hypotheses, if needed
216     InitAvailableHypotheses();
217
218     // fill list of hypotheses/algorithms
219     THypothesisDataMap* pMap = isAlgo ? &myAlgorithmsMap : &myHypothesesMap;
220     THypothesisDataMap::iterator anIter;
221     for ( anIter = pMap->begin(); anIter != pMap->end(); anIter++ )
222     {
223       HypothesisData* aData = (*anIter).second;
224       if ( ( theDim < 0 || aData->Dim.contains( theDim ) ) && aData->IsAux == isAux )
225         aHypList.append(((*anIter).first).c_str());
226     }
227     return aHypList;
228   }
229
230
231   QStringList GetHypothesesSets()
232   {
233     QStringList aSetNameList;
234
235     // Init list of available hypotheses, if needed
236     InitAvailableHypotheses();
237
238     list<HypothesesSet*>::iterator hypoSet = myListOfHypothesesSets.begin();
239     for ( ; hypoSet != myListOfHypothesesSets.end(); ++hypoSet )
240     {
241       HypothesesSet* aSet = *hypoSet;
242       if ( aSet && aSet->AlgoList.count() ) {
243         aSetNameList.append( aSet->HypoSetName );
244       }
245     }
246
247     return aSetNameList;
248   }
249
250   HypothesesSet* GetHypothesesSet(const QString theSetName)
251   {
252     list<HypothesesSet*>::iterator hypoSet = myListOfHypothesesSets.begin();
253     for ( ; hypoSet != myListOfHypothesesSets.end(); ++hypoSet )
254     {
255       HypothesesSet* aSet = *hypoSet;
256       if ( aSet && aSet->HypoSetName == theSetName )
257         return aSet;
258     }
259     return 0;
260   }
261
262   HypothesisData* GetHypothesisData (const char* aHypType)
263   {
264     HypothesisData* aHypData = 0;
265
266     // Init list of available hypotheses, if needed
267     InitAvailableHypotheses();
268
269     THypothesisDataMap::iterator type_data = myHypothesesMap.find(aHypType);
270     if (type_data != myHypothesesMap.end()) {
271       aHypData = type_data->second;
272     }
273     else {
274       type_data = myAlgorithmsMap.find(aHypType);
275       if (type_data != myAlgorithmsMap.end())
276         aHypData = type_data->second;
277     }
278     return aHypData;
279   }
280
281   bool IsAvailableHypothesis(const HypothesisData* algoData,
282                              const QString&        hypType,
283                              bool&                 isAuxiliary)
284   {
285     isAuxiliary = false;
286     if ( !algoData )
287       return false;
288     if ( algoData->NeededHypos.contains( hypType ))
289       return true;
290     if ( algoData->OptionalHypos.contains( hypType)) {
291       isAuxiliary = true;
292       return true;
293     }
294     return false;
295   }
296
297   bool IsCompatibleAlgorithm(const HypothesisData* algo1Data,
298                              const HypothesisData* algo2Data)
299   {
300     if ( !algo1Data || !algo2Data )
301       return false;
302     const HypothesisData* algoIn = algo1Data, *algoMain = algo2Data;
303     if ( algoIn->Dim.first() > algoMain->Dim.first() ) {
304       algoIn = algo2Data; algoMain = algo1Data;
305     }
306     // look for any output type of algoIn between input types of algoMain
307     QStringList::const_iterator inElemType = algoIn->OutputTypes.begin();
308     for ( ; inElemType != algoIn->OutputTypes.end(); ++inElemType )
309       if ( algoMain->InputTypes.contains( *inElemType ))
310         return true;
311     return false;
312   }
313
314   SMESHGUI_GenericHypothesisCreator* GetHypothesisCreator(const char* aHypType)
315   {
316     if(MYDEBUG) MESSAGE("Get HypothesisCreator for " << aHypType);
317
318     SMESHGUI_GenericHypothesisCreator* aCreator = 0;
319
320     // check, if creator for this hypothesis type already exists
321     if (myHypCreatorMap.find(aHypType) != myHypCreatorMap.end()) {
322       aCreator = myHypCreatorMap[aHypType];
323     }
324     else {
325       // 1. Init list of available hypotheses, if needed
326       InitAvailableHypotheses();
327
328       // 2. Get names of plugin libraries
329       HypothesisData* aHypData = GetHypothesisData(aHypType);
330       if (!aHypData) 
331         return aCreator;
332       QString aClientLibName = aHypData->ClientLibName;
333       QString aServerLibName = aHypData->ServerLibName;
334
335       // 3. Load Client Plugin Library
336       try {
337         // load plugin library
338         if(MYDEBUG) MESSAGE("Loading client meshers plugin library ...");
339         LibHandle libHandle = LoadLib( aClientLibName );
340         if (!libHandle) {
341           // report any error, if occured
342     if ( MYDEBUG )
343     {
344 #ifdef WIN32
345       const char* anError = "Can't load client meshers plugin library";
346 #else
347             const char* anError = dlerror();      
348 #endif
349       MESSAGE(anError);
350     }
351         }
352         else {
353           // get method, returning hypothesis creator
354           if(MYDEBUG) MESSAGE("Find GetHypothesisCreator() method ...");
355           typedef SMESHGUI_GenericHypothesisCreator* (*GetHypothesisCreator) \
356             ( const QString& );
357           GetHypothesisCreator procHandle =
358             (GetHypothesisCreator)GetProc(libHandle, "GetHypothesisCreator");
359           if (!procHandle) {
360             if(MYDEBUG) MESSAGE("bad hypothesis client plugin library");
361             UnLoadLib(libHandle);
362           }
363           else {
364             // get hypothesis creator
365             if(MYDEBUG) MESSAGE("Get Hypothesis Creator for " << aHypType);
366             aCreator = procHandle( aHypType );
367             if (!aCreator) {
368               if(MYDEBUG) MESSAGE("no such a hypothesis in this plugin");
369             }
370             else {
371               // map hypothesis creator to a hypothesis name
372               myHypCreatorMap[aHypType] = aCreator;
373             }
374           }
375         }
376       }
377       catch (const SALOME::SALOME_Exception& S_ex) {
378         SalomeApp_Tools::QtCatchCorbaException(S_ex);
379       }
380     }
381
382     return aCreator;
383   }
384
385
386   SMESH::SMESH_Hypothesis_ptr CreateHypothesis(const char* aHypType,
387                                                const char* aHypName,
388                                                const bool isAlgo)
389   {
390     if(MYDEBUG) MESSAGE("Create " << aHypType << " with name " << aHypName);
391     HypothesisData* aHypData = GetHypothesisData(aHypType);
392     QString aServLib = aHypData->ServerLibName;
393     try {
394       SMESH::SMESH_Hypothesis_var aHypothesis;
395       aHypothesis = SMESHGUI::GetSMESHGen()->CreateHypothesis(aHypType, aServLib);
396       if (!aHypothesis->_is_nil()) {
397         _PTR(SObject) aHypSObject = SMESH::FindSObject(aHypothesis.in());
398         if (aHypSObject) {
399           if (strlen(aHypName) > 0)
400             SMESH::SetName(aHypSObject, aHypName);
401           SMESHGUI::GetSMESHGUI()->updateObjBrowser();
402           return aHypothesis._retn();
403         }
404       }
405     } catch (const SALOME::SALOME_Exception & S_ex) {
406       SalomeApp_Tools::QtCatchCorbaException(S_ex);
407     }
408
409     return SMESH::SMESH_Hypothesis::_nil();
410   }
411
412
413   bool AddHypothesisOnMesh (SMESH::SMESH_Mesh_ptr aMesh, SMESH::SMESH_Hypothesis_ptr aHyp)
414   {
415     if(MYDEBUG) MESSAGE ("SMESHGUI::AddHypothesisOnMesh");
416     int res = SMESH::HYP_UNKNOWN_FATAL;
417     SUIT_OverrideCursor wc;
418
419     if (!aMesh->_is_nil()) {
420       _PTR(SObject) SM = SMESH::FindSObject(aMesh);
421       GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(SM);
422       try {
423         res = aMesh->AddHypothesis(aShapeObject, aHyp);
424         if (res < SMESH::HYP_UNKNOWN_FATAL) {
425           _PTR(SObject) aSH = SMESH::FindSObject(aHyp);
426           if (SM && aSH) {
427             SMESH::ModifiedMesh(SM, false, aMesh->NbNodes()==0);
428           }
429         }
430         if (res > SMESH::HYP_OK) {
431           wc.suspend();
432           processHypothesisStatus(res, aHyp, true);
433           wc.resume();
434         }
435       }
436       catch(const SALOME::SALOME_Exception& S_ex) {
437         wc.suspend();
438         SalomeApp_Tools::QtCatchCorbaException(S_ex);
439         res = SMESH::HYP_UNKNOWN_FATAL;
440       }
441     }
442     return res < SMESH::HYP_UNKNOWN_FATAL;
443   }
444
445
446   bool AddHypothesisOnSubMesh (SMESH::SMESH_subMesh_ptr aSubMesh, SMESH::SMESH_Hypothesis_ptr aHyp)
447   {
448     if(MYDEBUG) MESSAGE("SMESHGUI::AddHypothesisOnSubMesh() ");
449     int res = SMESH::HYP_UNKNOWN_FATAL;
450     SUIT_OverrideCursor wc;
451
452     if (!aSubMesh->_is_nil() && ! aHyp->_is_nil()) {
453       try {
454         SMESH::SMESH_Mesh_var aMesh = aSubMesh->GetFather();
455         _PTR(SObject) SsubM = SMESH::FindSObject(aSubMesh);
456         GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(SsubM);
457         if (!aMesh->_is_nil() && SsubM && !aShapeObject->_is_nil()) {
458           res = aMesh->AddHypothesis(aShapeObject, aHyp);
459           if (res < SMESH::HYP_UNKNOWN_FATAL)  {
460             _PTR(SObject) meshSO = SMESH::FindSObject(aMesh);
461             if (meshSO)
462               SMESH::ModifiedMesh(meshSO, false, aMesh->NbNodes()==0);
463           }
464           if (res > SMESH::HYP_OK) {
465             wc.suspend();
466             processHypothesisStatus(res, aHyp, true);
467             wc.resume();
468           }
469         }
470         else {
471           SCRUTE(aHyp->_is_nil());
472           SCRUTE(aMesh->_is_nil());
473           SCRUTE(!SsubM);
474           SCRUTE(aShapeObject->_is_nil());
475         }
476       }
477       catch(const SALOME::SALOME_Exception& S_ex) {
478         wc.suspend();
479         SalomeApp_Tools::QtCatchCorbaException(S_ex);
480         res = SMESH::HYP_UNKNOWN_FATAL;
481       }
482     }
483     else {
484       SCRUTE(aSubMesh->_is_nil());
485       SCRUTE(aHyp->_is_nil());
486     }
487     return res < SMESH::HYP_UNKNOWN_FATAL;
488   }
489
490   bool RemoveHypothesisOrAlgorithmOnMesh (const Handle(SALOME_InteractiveObject)& IObject)
491   {
492     int res = SMESH::HYP_UNKNOWN_FATAL;
493     SUIT_OverrideCursor wc;
494
495     try {
496       _PTR(Study) aStudy = GetActiveStudyDocument();
497       _PTR(SObject) aHypObj = aStudy->FindObjectID( IObject->getEntry() );
498       if( aHypObj )
499       {
500         _PTR(SObject) MorSM = SMESH::GetMeshOrSubmesh( aHypObj );
501         _PTR(SObject) aRealHypo;
502         if( aHypObj->ReferencedObject( aRealHypo ) )
503         {
504           SMESH_Hypothesis_var hypo = SMESH_Hypothesis::_narrow( SObjectToObject( aRealHypo ) );
505           RemoveHypothesisOrAlgorithmOnMesh( MorSM, hypo );
506         }
507         else
508         {
509           SMESH_Hypothesis_var hypo = SMESH_Hypothesis::_narrow( SObjectToObject( aHypObj ) );
510           SObjectList meshList = GetMeshesUsingAlgoOrHypothesis( hypo );
511           for( int i = 0; i < meshList.size(); i++ )
512             RemoveHypothesisOrAlgorithmOnMesh( meshList[ i ], hypo );
513         }
514       }
515     }
516     catch(const SALOME::SALOME_Exception& S_ex)
517     {
518       wc.suspend();
519       SalomeApp_Tools::QtCatchCorbaException(S_ex);
520       res = SMESH::HYP_UNKNOWN_FATAL;
521     }
522     return res < SMESH::HYP_UNKNOWN_FATAL;
523   }
524
525   bool RemoveHypothesisOrAlgorithmOnMesh (_PTR(SObject) MorSM,
526                                           SMESH::SMESH_Hypothesis_ptr anHyp)
527   {
528     SALOMEDS::GenericAttribute_var anAttr;
529     SALOMEDS::AttributeIOR_var anIOR;
530     int res = SMESH::HYP_UNKNOWN_FATAL;
531     SUIT_OverrideCursor wc;
532
533     if (MorSM) {
534       try {
535         GEOM::GEOM_Object_var aShapeObject = SMESH::GetShapeOnMeshOrSubMesh(MorSM);
536         if (!aShapeObject->_is_nil()) {
537           SMESH::SMESH_Mesh_var aMesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>(MorSM);
538           SMESH::SMESH_subMesh_var aSubMesh = SMESH::SObjectToInterface<SMESH::SMESH_subMesh>(MorSM);
539
540           if (!aSubMesh->_is_nil())
541             aMesh = aSubMesh->GetFather();
542
543           if (!aMesh->_is_nil()) {
544             res = aMesh->RemoveHypothesis(aShapeObject, anHyp);
545             if (res < SMESH::HYP_UNKNOWN_FATAL) {
546               _PTR(SObject) meshSO = SMESH::FindSObject(aMesh);
547               if (meshSO)
548                 SMESH::ModifiedMesh(meshSO, false, aMesh->NbNodes()==0);
549             }
550             if (res > SMESH::HYP_OK) {
551               wc.suspend();
552               processHypothesisStatus(res, anHyp, false);
553               wc.resume();
554             }
555           }
556         }
557       } catch(const SALOME::SALOME_Exception& S_ex) {
558         wc.suspend();
559         SalomeApp_Tools::QtCatchCorbaException(S_ex);
560         res = SMESH::HYP_UNKNOWN_FATAL;
561       }
562     }
563     return res < SMESH::HYP_UNKNOWN_FATAL;
564   }
565
566   SObjectList GetMeshesUsingAlgoOrHypothesis(SMESH::SMESH_Hypothesis_ptr AlgoOrHyp)
567   {
568     SObjectList listSOmesh;
569     listSOmesh.resize(0);
570
571     unsigned int index = 0;
572     if (!AlgoOrHyp->_is_nil()) {
573       _PTR(SObject) SO_Hypothesis = SMESH::FindSObject(AlgoOrHyp);
574       if (SO_Hypothesis) {
575         SObjectList listSO =
576           SMESHGUI::activeStudy()->studyDS()->FindDependances(SO_Hypothesis);
577
578         if(MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): dependency number ="<<listSO.size());
579         for (unsigned int i = 0; i < listSO.size(); i++) {
580           _PTR(SObject) SO = listSO[i];
581           if (SO) {
582             _PTR(SObject) aFather = SO->GetFather();
583             if (aFather) {
584               _PTR(SObject) SOfatherFather = aFather->GetFather();
585               if (SOfatherFather) {
586                 if(MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): dependency added to list");
587                 index++;
588                 listSOmesh.resize(index);
589                 listSOmesh[index - 1] = SOfatherFather;
590               }
591             }
592           }
593         }
594       }
595     }
596     if (MYDEBUG) MESSAGE("SMESHGUI::GetMeshesUsingAlgoOrHypothesis(): completed");
597     return listSOmesh;
598   }
599
600 #define CASE2MESSAGE(enum) case SMESH::enum: msg = QObject::tr( "STATE_" #enum ); break;
601   QString GetMessageOnAlgoStateErrors(const algo_error_array& errors)
602   {
603     QString resMsg = QObject::tr("SMESH_WRN_MISSING_PARAMETERS") + ":\n";
604     for ( int i = 0; i < errors.length(); ++i ) {
605       const SMESH::AlgoStateError & error = errors[ i ];
606       const bool hasAlgo = ( strlen( error.algoName ) != 0 );
607       QString msg;
608       if ( !hasAlgo )
609         msg = QObject::tr( "STATE_ALGO_MISSING" );
610       else 
611         switch( error.state ) {
612           CASE2MESSAGE( HYP_MISSING );
613           CASE2MESSAGE( HYP_NOTCONFORM );
614           CASE2MESSAGE( HYP_BAD_PARAMETER );
615           CASE2MESSAGE( HYP_BAD_GEOMETRY );
616         default: continue;
617         }
618       // apply args to message:
619       // %1 - algo name
620       if ( hasAlgo )
621         msg = msg.arg( error.algoName.in() );
622       // %2 - dimension
623       msg = msg.arg( error.algoDim );
624       // %3 - global/local
625       msg = msg.arg( QObject::tr( error.isGlobalAlgo ? "GLOBAL_ALGO" : "LOCAL_ALGO" ));
626       // %4 - hypothesis dim == algoDim
627       msg = msg.arg( error.algoDim );
628
629       if ( i ) resMsg += ";\n";
630       resMsg += msg;
631     }
632     return resMsg;
633   }
634
635 }