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