Salome HOME
IPAL52460: Optimal Axes button is inert when edit body fitting parameters
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MeshOp.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : SMESHGUI_MeshOp.cxx
23 //  Author : Sergey LITONIN, Open CASCADE S.A.S.
24
25 // SMESH includes
26 #include "SMESHGUI_MeshOp.h"
27
28 #include "SMESHGUI.h"
29 #include "SMESHGUI_MeshDlg.h"
30 #include "SMESHGUI_ShapeByMeshDlg.h"
31 #include "SMESHGUI_HypothesesUtils.h"
32 #include "SMESHGUI_Hypotheses.h"
33 #include "SMESHGUI_Utils.h"
34 #include "SMESHGUI_GEOMGenUtils.h"
35
36 #include <SMESH_TypeFilter.hxx>
37 #include <SMESH_NumberFilter.hxx>
38
39 // SALOME GEOM includes
40 #include <GEOM_SelectionFilter.h>
41 #include <GEOMBase.h>
42 #include <GeometryGUI.h>
43 #include <GEOM_wrap.hxx>
44 #include <GEOMImpl_Types.hxx>
45
46 // SALOME GUI includes
47 #include <SalomeApp_Tools.h>
48 #include <SalomeApp_Application.h>
49 #include <LightApp_Application.h>
50 #include <LightApp_SelectionMgr.h>
51 #include <LightApp_UpdateFlags.h>
52 #include <SUIT_MessageBox.h>
53 #include <SUIT_OverrideCursor.h>
54 #include <SUIT_Session.h>
55 #include <SALOME_InteractiveObject.hxx>
56 #include <SALOME_ListIO.hxx>
57
58 // SALOME KERNEL includes
59 #include <SALOMEDS_SComponent.hxx>
60 #include <SALOMEDS_SObject.hxx>
61 #include <SALOMEDS_Study.hxx>
62 #include <SALOMEDS_wrap.hxx>
63
64 // Qt includes
65 #include <QStringList>
66 #include <QLineEdit>
67 #include <QApplication>
68
69 // OCCT includes
70 #include <TopoDS.hxx>
71 #include <TopoDS_Shape.hxx>
72 #include <TopoDS_Shell.hxx>
73 #include <TopExp_Explorer.hxx>
74 #include <BRep_Tool.hxx>
75
76 // IDL includes
77 #include <SALOMEconfig.h>
78 #include CORBA_CLIENT_HEADER(SMESH_Gen)
79
80 //================================================================================
81 /*!
82  * \brief Constructor
83   * \param theToCreate - if this parameter is true then operation is used for creation,
84   * for editing otherwise
85  *
86  * Initialize operation
87 */
88 //================================================================================
89 SMESHGUI_MeshOp::SMESHGUI_MeshOp( const bool theToCreate, const bool theIsMesh )
90 : SMESHGUI_SelectionOp(),
91   myToCreate( theToCreate ),
92   myIsMesh( theIsMesh ),
93   myDlg( 0 ),
94   myShapeByMeshOp( 0 ),
95   myHypoSet( 0 )
96 {
97   if ( GeometryGUI::GetGeomGen()->_is_nil() )// check that GEOM_Gen exists
98     GeometryGUI::InitGeomGen();
99   myIsOnGeometry = true;
100   myMaxShapeDim = -1;
101 }
102
103 //================================================================================
104 /*!
105  * \brief Destructor
106 */
107 //================================================================================
108 SMESHGUI_MeshOp::~SMESHGUI_MeshOp()
109 {
110   if ( myDlg )
111     delete myDlg;
112 }
113
114 //================================================================================
115 /*!
116  * \brief Gets dialog of this operation
117   * \retval LightApp_Dialog* - pointer to dialog of this operation
118 */
119 //================================================================================
120 LightApp_Dialog* SMESHGUI_MeshOp::dlg() const
121 {
122   return myDlg;
123 }
124
125 //================================================================================
126 /*!
127  * \brief Creates or edits mesh
128   * \retval bool - TRUE if operation is performed successfully, FALSE otherwise
129  *
130  * Virtual slot redefined from the base class called when "Apply" button is clicked
131  * creates or edits mesh
132  */
133 //================================================================================
134 bool SMESHGUI_MeshOp::onApply()
135 {
136   if (isStudyLocked())
137     return false;
138
139   QString aMess;
140   if ( !isValid( aMess ) )
141   {
142     dlg()->show();
143     if ( aMess != "" )
144       SUIT_MessageBox::warning( myDlg, tr( "SMESH_WRN_WARNING" ), aMess );
145     return false;
146   }
147
148   bool aResult = false;
149   aMess = "";
150   try
151   {
152     QStringList anEntryList;
153     if ( myToCreate && myIsMesh )
154       aResult = createMesh( aMess, anEntryList );
155     if ( myToCreate && !myIsMesh )
156       aResult = createSubMesh( aMess, anEntryList );
157     else if ( !myToCreate )
158       aResult = editMeshOrSubMesh( aMess );
159     if ( aResult )
160     {
161       SMESHGUI::Modified();
162       update( UF_ObjBrowser | UF_Model );
163       if( LightApp_Application* anApp =
164           dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() ) )
165         myObjectToSelect = anApp->browseObjects( anEntryList, isApplyAndClose() );
166     }
167   }
168   catch ( const SALOME::SALOME_Exception& S_ex )
169   {
170     SalomeApp_Tools::QtCatchCorbaException( S_ex );
171     aResult = false;
172   }
173   catch ( ... )
174   {
175     aResult = false;
176   }
177
178   if ( aResult )
179   {
180     if ( myToCreate )
181       setDefaultName();
182   }
183   else
184   {
185     if ( aMess == "" )
186       aMess = tr( "SMESH_OPERATION_FAILED" );
187     SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ), aMess );
188   }
189
190   return aResult;
191 }
192
193 //================================================================================
194 /*!
195  * \brief Creates dialog if necessary and shows it
196  *
197  * Virtual method redefined from base class called when operation is started creates
198  * dialog if necessary and shows it, activates selection
199  */
200 //================================================================================
201 void SMESHGUI_MeshOp::startOperation()
202 {
203   if (!myDlg)
204   {
205     myDlg = new SMESHGUI_MeshDlg( myToCreate, myIsMesh );
206     for ( int i = SMESH::DIM_0D; i <= SMESH::DIM_3D; i++ )
207     {
208       connect( myDlg->tab( i ), SIGNAL( createHyp( const int, const int ) ),
209               this, SLOT( onCreateHyp( const int, const int ) ) );
210       connect( myDlg->tab( i ), SIGNAL( editHyp( const int, const int ) ),
211               this, SLOT( onEditHyp( const int, const int ) ) );
212       connect( myDlg->tab( i ), SIGNAL( selectAlgo( const int ) ),
213               this, SLOT( onAlgoSelected( const int ) ) );
214     }
215     connect( myDlg, SIGNAL( hypoSet( const QString& )), SLOT( onHypoSet( const QString& )));
216     connect( myDlg, SIGNAL( geomSelectionByMesh( bool )), SLOT( onGeomSelectionByMesh( bool )));
217     connect( myDlg, SIGNAL( selectMeshType( const int, const int ) ), SLOT( onAlgoSetByMeshType( const int, const int)));
218     if ( myToCreate ) {
219       if ( myIsMesh ) myHelpFileName = "constructing_meshes_page.html";
220       else            myHelpFileName = "constructing_submeshes_page.html";
221     }
222     else {
223       myHelpFileName = "editing_meshes_page.html";
224     }
225   }
226   SMESHGUI_SelectionOp::startOperation();
227   // iterate through dimensions and get available algoritms, set them to the dialog
228   _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
229   for ( int i = SMESH::DIM_0D; i <= SMESH::DIM_3D; i++ )
230   {
231     SMESHGUI_MeshTab* aTab = myDlg->tab( i );
232     QStringList hypList;
233     // clear available hypotheses
234     aTab->setAvailableHyps( MainHyp, hypList );
235     aTab->setAvailableHyps( AddHyp, hypList );
236     aTab->setExistingHyps( MainHyp, hypList );
237     aTab->setExistingHyps( AddHyp, hypList );
238     myExistingHyps[ i ][ MainHyp ].clear();
239     myExistingHyps[ i ][ AddHyp ].clear();
240     // set algos
241     availableHyps( i, Algo, hypList, myAvailableHypData[i][Algo] );
242     aTab->setAvailableHyps( Algo, hypList );
243   }
244   if ( myToCreate )
245   {
246     setDefaultName();
247     myDlg->activateObject( myIsMesh ? SMESHGUI_MeshDlg::Geom : SMESHGUI_MeshDlg::Mesh );
248   }
249   else
250     myDlg->activateObject( SMESHGUI_MeshDlg::Obj );
251
252   myDlg->setCurrentTab( SMESH::DIM_3D );
253
254   QStringList TypeMeshList;
255   createMeshTypeList( TypeMeshList );
256   setAvailableMeshType( TypeMeshList );
257
258   myDlg->show();
259   myDlg->setGeomPopupEnabled(false);
260   selectionDone();
261
262   myIgnoreAlgoSelection = false;
263   myHasConcurrentSubBefore = false;
264
265   myObjectToSelect.clear();
266 }
267
268 //=================================================================================
269 /*!
270  * \brief Selects a recently created mesh or sub-mesh if necessary
271  *
272  * Virtual method redefined from base class called when operation is commited
273  * selects a recently created mesh or sub-mesh if necessary. Allows to perform
274  * selection when the custom selection filters are removed.
275  */
276 //=================================================================================
277 void SMESHGUI_MeshOp::commitOperation()
278 {
279   SMESHGUI_SelectionOp::commitOperation();
280
281   if ( !myObjectToSelect.isEmpty() ) {
282     if ( LightApp_SelectionMgr* aSelectionMgr = selectionMgr() ) {
283       SUIT_DataOwnerPtrList aList;
284       aList.append( new LightApp_DataOwner( myObjectToSelect ) );
285       aSelectionMgr->setSelected( aList );
286     }
287   }
288 }
289
290 //================================================================================
291 /*!
292  * \brief Creates selection filter
293   * \param theId - identifier of current selection widget
294   * \retval SUIT_SelectionFilter* - pointer to the created filter or null
295  *
296  * Creates selection filter in accordance with identifier of current selection widget
297  */
298 //================================================================================
299 SUIT_SelectionFilter* SMESHGUI_MeshOp::createFilter( const int theId ) const
300 {
301   if ( theId == SMESHGUI_MeshDlg::Geom )
302   {
303 //     TColStd_MapOfInteger allTypesMap;
304 //     for ( int i = 0; i < 10; i++ )
305 //       allTypesMap.Add( i );
306 //     return new SMESH_NumberFilter( "GEOM", TopAbs_SHAPE, 0, allTypesMap );
307     return new GEOM_SelectionFilter( (SalomeApp_Study*)study(), true );
308   }
309   else if ( theId == SMESHGUI_MeshDlg::Obj && !myToCreate )
310     return new SMESH_TypeFilter( SMESH::MESHorSUBMESH );
311   else if ( theId == SMESHGUI_MeshDlg::Mesh )
312     return new SMESH_TypeFilter( SMESH::MESH );
313   else
314     return 0;
315 }
316
317 //================================================================================
318 /*!
319  * \brief check if selected shape is a sub-shape of the shape to mesh
320   * \retval bool - check result
321  */
322 //================================================================================
323 bool SMESHGUI_MeshOp::isSubshapeOk() const
324 {
325   if ( !myToCreate || myIsMesh ) // not submesh creation
326     return false;
327
328   // mesh
329   QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
330   _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.toLatin1().data() );
331   if (!pMesh) return false;
332
333   SMESH::SMESH_Mesh_var mesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( pMesh );
334   if (mesh->_is_nil()) return false;
335
336   // main shape of the mesh
337   GEOM::GEOM_Object_var mainGeom = mesh->GetShapeToMesh();
338   if (mainGeom->_is_nil()) return false;
339
340   // geometry
341   QStringList aGEOMs;
342   myDlg->selectedObject(SMESHGUI_MeshDlg::Geom, aGEOMs);
343
344   if (aGEOMs.count() > 0) {
345     GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen();
346     _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
347     if (geomGen->_is_nil() || !aStudy) return false;
348
349     GEOM::GEOM_IGroupOperations_wrap op = geomGen->GetIGroupOperations(aStudy->StudyId());
350     if (op->_is_nil()) return false;
351
352     // check all selected shapes
353     QStringList::const_iterator aSubShapesIter = aGEOMs.begin();
354     for ( ; aSubShapesIter != aGEOMs.end(); aSubShapesIter++) {
355       QString aSubGeomEntry = (*aSubShapesIter);
356       _PTR(SObject) pSubGeom = studyDS()->FindObjectID(aSubGeomEntry.toLatin1().data());
357       if (!pSubGeom) return false;
358
359       GEOM::GEOM_Object_var aSubGeomVar =
360         GEOM::GEOM_Object::_narrow(_CAST(SObject,pSubGeom)->GetObject());
361       if (aSubGeomVar->_is_nil()) return false;
362
363       // skl for NPAL14695 - implementation of searching of mainObj
364       GEOM::GEOM_Object_var mainObj = op->GetMainShape(aSubGeomVar); /* _var not _wrap as
365                                                                         mainObj already exists! */
366       while(1) {
367         if (mainObj->_is_nil())
368           return false;
369         CORBA::String_var entry1 = mainObj->GetEntry();
370         CORBA::String_var entry2 = mainGeom->GetEntry();
371         if (std::string( entry1.in() ) == entry2.in() )
372           return true;
373         mainObj = op->GetMainShape(mainObj);
374       }
375     }
376   }
377
378   return false;
379 }
380
381 //================================================================================
382 /*!
383  * \brief Return name of the algorithm that does not support submeshes and makes
384  * submesh creation useless
385  *  \retval char* - string is to be deleted!!!
386  */
387 //================================================================================
388 char* SMESHGUI_MeshOp::isSubmeshIgnored() const
389 {
390   if ( myToCreate && !myIsMesh ) {
391
392     QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
393     QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
394     _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.toLatin1().data() );
395     if ( pMesh ) {
396
397       QStringList algoNames;
398       THypList    algoList;
399       existingHyps(3, Algo, pMesh, algoNames, algoList);
400       if (!algoList.empty()) {
401         HypothesisData* algo =
402           SMESH::GetHypothesisData( SMESH::toQStr( algoList[0].first->GetName() ));
403         if ( algo &&
404              algo->InputTypes.empty() && // builds all dimensions it-self
405              !algo->IsSupportSubmeshes )
406           return CORBA::string_dup( algoNames[0].toLatin1().data() );
407       }
408
409 //       GEOM::GEOM_Object_var geom;
410 //       if (_PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.toLatin1().data() ))
411 //         geom = SMESH::SObjectToInterface<GEOM::GEOM_Object>( pGeom );
412
413 //       if ( !geom->_is_nil() && geom->GetShapeType() >= GEOM::FACE ) { // WIRE, EDGE as well
414         existingHyps(2, Algo, pMesh, algoNames, algoList);
415         if (!algoList.empty()) {
416           HypothesisData* algo =
417             SMESH::GetHypothesisData( SMESH::toQStr( algoList[0].first->GetName() ));
418           if ( algo &&
419                algo->InputTypes.empty() && // builds all dimensions it-self
420                !algo->IsSupportSubmeshes )
421             return CORBA::string_dup( algoNames[0].toLatin1().data() );
422         }
423 //       }
424     }
425   }
426   return 0;
427 }
428
429 //================================================================================
430 /*!
431  * \brief find an existing submesh by the selected shape
432  * \retval _PTR(SObject) - the found submesh SObject
433  */
434 //================================================================================
435 _PTR(SObject) SMESHGUI_MeshOp::getSubmeshByGeom() const
436 {
437   QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
438   QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
439   _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.toLatin1().data() );
440   _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.toLatin1().data() );
441   if ( pMesh && pGeom ) {
442     GEOM::GEOM_Object_var geom = SMESH::SObjectToInterface<GEOM::GEOM_Object>( pGeom );
443     if ( !geom->_is_nil() ) {
444       int tag = -1;
445       switch ( geom->GetShapeType() ) {
446       case GEOM::VERTEX:   tag = SMESH::Tag_SubMeshOnVertex;   break;
447       case GEOM::EDGE:     tag = SMESH::Tag_SubMeshOnEdge;     break;
448       case GEOM::WIRE:     tag = SMESH::Tag_SubMeshOnWire;     break;
449       case GEOM::FACE:     tag = SMESH::Tag_SubMeshOnFace;     break;
450       case GEOM::SHELL:    tag = SMESH::Tag_SubMeshOnShell;    break;
451       case GEOM::SOLID:    tag = SMESH::Tag_SubMeshOnSolid;    break;
452       case GEOM::COMPOUND: tag = SMESH::Tag_SubMeshOnCompound; break;
453       default:;
454       }
455       _PTR(GenericAttribute) anAttr;
456       _PTR(SObject) aSubmeshRoot;
457       _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
458       if ( pMesh->FindSubObject( tag, aSubmeshRoot ) )
459       {
460         _PTR(ChildIterator) smIter = aStudy->NewChildIterator( aSubmeshRoot );
461         for ( ; smIter->More(); smIter->Next() )
462         {
463           _PTR(SObject) aSmObj = smIter->Value();
464           if ( ! aSmObj->FindAttribute( anAttr, "AttributeIOR" ))
465             continue;
466           _PTR(ChildIterator) anIter1 = aStudy->NewChildIterator(aSmObj);
467           for ( ; anIter1->More(); anIter1->Next()) {
468             _PTR(SObject) pGeom2 = anIter1->Value();
469             if ( pGeom2->ReferencedObject( pGeom2 ) &&
470                  pGeom2->GetID() == pGeom->GetID() )
471               return aSmObj;
472           }
473         }
474       }
475     }
476   }
477   return _PTR(SObject)();
478 }
479
480 //================================================================================
481 /*!
482  * \brief Updates dialog's look and feel
483  *
484  * Virtual method redefined from the base class updates dialog's look and feel
485  */
486 //================================================================================
487 void SMESHGUI_MeshOp::selectionDone()
488 {
489   if (!dlg()->isVisible() || !myDlg->isEnabled())
490     return;
491
492   SMESHGUI_SelectionOp::selectionDone();
493
494   try
495   {
496     myIsOnGeometry = true;
497
498     //Check geometry for mesh
499     QString anObjEntry = myDlg->selectedObject(SMESHGUI_MeshDlg::Obj);
500     _PTR(SObject) pObj = studyDS()->FindObjectID(anObjEntry.toLatin1().data());
501     if (pObj)
502     {
503       SMESH::SMESH_Mesh_var aMeshVar =
504         SMESH::SMESH_Mesh::_narrow(_CAST(SObject,pObj)->GetObject());
505       if (!aMeshVar->_is_nil()) {
506         if (!myToCreate && !aMeshVar->HasShapeToMesh())
507           myIsOnGeometry = false;
508       }
509     }
510
511     if (myIsOnGeometry)
512     {
513       // Enable tabs according to shape dimension
514
515       int shapeDim = 3;
516
517       QStringList aGEOMs;
518       myDlg->selectedObject(SMESHGUI_MeshDlg::Geom, aGEOMs);
519       GEOM::ListOfGO_var aSeq = new GEOM::ListOfGO;
520
521       if (aGEOMs.count() > 0) {
522         // one or more GEOM shape selected
523         aSeq->length(aGEOMs.count());
524         QStringList::const_iterator aSubShapesIter = aGEOMs.begin();
525         int iSubSh = 0;
526         for ( ; aSubShapesIter != aGEOMs.end(); aSubShapesIter++, iSubSh++) {
527           QString aSubGeomEntry = (*aSubShapesIter);
528           _PTR(SObject) pSubGeom = studyDS()->FindObjectID(aSubGeomEntry.toLatin1().data());
529           GEOM::GEOM_Object_var aSubGeomVar =
530             GEOM::GEOM_Object::_narrow(_CAST(SObject,pSubGeom)->GetObject());
531           aSeq[iSubSh] = aSubGeomVar;
532         }
533       } else {
534         // get geometry by selected sub-mesh
535         QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
536         _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.toLatin1().data() );
537         GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj );
538         if (!aGeomVar->_is_nil()) {
539           aSeq->length(1);
540           aSeq[0] = aGeomVar;
541         }
542       }
543
544       if (aSeq->length() > 0) {
545         shapeDim = -1;
546         for (int iss = 0; iss < aSeq->length() && shapeDim < 3; iss++) {
547           GEOM::GEOM_Object_var aGeomVar = aSeq[iss];
548           switch ( aGeomVar->GetShapeType() ) {
549           case GEOM::SOLID:  shapeDim = 3; break;
550           case GEOM::SHELL:
551             // Bug 0016155: EDF PAL 447: If the shape is a Shell, disable 3D tab
552             // {
553             //   TopoDS_Shape aShape;
554             //   bool isClosed = GEOMBase::GetShape(aGeomVar, aShape) && /*aShape.Closed()*/BRep_Tool::IsClosed(aShape);
555             //   shapeDim = qMax(isClosed ? 3 : 2, shapeDim);
556             // }
557             // break;
558           case GEOM::FACE:   shapeDim = qMax(2, shapeDim); break;
559           case GEOM::WIRE:
560           case GEOM::EDGE:   shapeDim = qMax(1, shapeDim); break;
561           case GEOM::VERTEX: shapeDim = qMax(0, shapeDim); break;
562           default:
563             {
564               TopoDS_Shape aShape;
565               if (GEOMBase::GetShape(aGeomVar, aShape))
566               {
567                 TopExp_Explorer exp (aShape, TopAbs_SOLID);
568                 if (exp.More()) {
569                   shapeDim = 3;
570                 }
571                 // Bug 0016155: EDF PAL 447: If the shape is a Shell, disable 3D tab
572                 // else if ( exp.Init( aShape, TopAbs_SHELL ), exp.More() )
573                 // {
574                 //   shapeDim = 2;
575                 //   for (; exp.More() && shapeDim == 2; exp.Next()) {
576                 //     if (/*exp.Current().Closed()*/BRep_Tool::IsClosed(exp.Current()))
577                 //       shapeDim = 3;
578                 //   }
579                 // }
580                 else if ( exp.Init( aShape, TopAbs_FACE ), exp.More() )
581                   shapeDim = qMax(2, shapeDim);
582                 else if ( exp.Init( aShape, TopAbs_EDGE ), exp.More() )
583                   shapeDim = qMax(1, shapeDim);
584                 else if ( exp.Init( aShape, TopAbs_VERTEX ), exp.More() )
585                   shapeDim = qMax(0, shapeDim);
586               }
587             }
588           }
589           if ( shapeDim == 3 )
590             break;
591         }
592       }
593       for (int i = SMESH::DIM_3D; i > shapeDim; i--) {
594         // reset algos before disabling tabs (0020138)
595         onAlgoSelected(-1, i);
596       }
597       myDlg->setMaxHypoDim( shapeDim );
598       myMaxShapeDim = shapeDim;
599       myDlg->setHypoSets( SMESH::GetHypothesesSets( shapeDim ));
600
601       if (!myToCreate) // edition: read hypotheses
602       {
603         if (pObj != 0)
604         {
605           SMESH::SMESH_subMesh_var submeshVar =
606             SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() );
607           myDlg->setObjectShown( SMESHGUI_MeshDlg::Mesh, !submeshVar->_is_nil() );
608           myDlg->setObjectShown( SMESHGUI_MeshDlg::Geom, true );
609           myDlg->objectWg( SMESHGUI_MeshDlg::Mesh, SMESHGUI_MeshDlg::Btn )->hide();
610           myDlg->objectWg( SMESHGUI_MeshDlg::Geom, SMESHGUI_MeshDlg::Btn )->hide();
611           myDlg->updateGeometry();
612           myDlg->adjustSize();
613           readMesh();
614           myIsMesh = submeshVar->_is_nil();
615         }
616         else
617           myDlg->reset();
618       }
619       else if ( !myIsMesh ) // submesh creation
620       {
621         // if a submesh on the selected shape already exist, pass to submesh edition mode
622         if ( _PTR(SObject) pSubmesh = getSubmeshByGeom() ) {
623           SMESH::SMESH_subMesh_var sm =
624             SMESH::SObjectToInterface<SMESH::SMESH_subMesh>( pSubmesh );
625           bool editSubmesh = ( !sm->_is_nil() &&
626                                SUIT_MessageBox::question( myDlg, tr( "SMESH_WARNING" ),
627                                                           tr( "EDIT_SUBMESH_QUESTION"),
628                                                           SUIT_MessageBox::Yes |
629                                                           SUIT_MessageBox::No,
630                                                           SUIT_MessageBox::No )
631                                == SUIT_MessageBox::Yes );
632           if ( editSubmesh )
633           {
634             selectionMgr()->clearFilters();
635             selectObject( pSubmesh );
636             SMESHGUI::GetSMESHGUI()->switchToOperation(704);
637             return;
638           }
639           else
640           {
641             myDlg->selectObject( "", SMESHGUI_MeshDlg::Geom, "" );
642             selectObject( _PTR(SObject)() );
643             selectionDone();
644             return;
645           }
646         }
647         // discard selected mesh if submesh creation not allowed because of
648         // a global algorithm that does not support submeshes
649         if ( char* algoName = isSubmeshIgnored() ) {
650           SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ),
651                                     tr("SUBMESH_NOT_ALLOWED").arg(algoName));
652           CORBA::string_free( algoName );
653           myDlg->selectObject( "", SMESHGUI_MeshDlg::Mesh, "" );
654           selectObject( _PTR(SObject)() );
655           selectionDone();
656           return;
657         }
658
659         // enable/disable popup for choice of geom selection way
660         bool enable = false;
661         QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
662         if ( _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.toLatin1().data() )) {
663           SMESH::SMESH_Mesh_var mesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( pMesh );
664           if ( !mesh->_is_nil() ) {
665             //rnv: issue 21056: EDF 1608 SMESH: Dialog Box "Create Sub Mesh": focus should automatically switch to geometry
666             QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
667             _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.toLatin1().data() );
668             if ( !pGeom || GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() )->_is_nil() )
669               myDlg->activateObject(SMESHGUI_MeshDlg::Geom);
670             enable = ( shapeDim > 1 ) && ( mesh->NbEdges() > 0 );
671           }
672         }
673         myDlg->setGeomPopupEnabled( enable );
674       }
675     }
676     else { // no geometry defined
677       myDlg->enableTab( SMESH::DIM_3D );
678       QStringList hypList;
679       availableHyps( SMESH::DIM_3D, Algo, hypList,
680                      myAvailableHypData[SMESH::DIM_3D][Algo]);
681
682       SMESHGUI_MeshTab* aTab = myDlg->tab( SMESH::DIM_3D );
683       aTab->setAvailableHyps( Algo, hypList );
684       for (int i = SMESH::DIM_0D;i < SMESH::DIM_3D; ++i) {
685         myDlg->disableTab(i);
686       }
687       myMaxShapeDim = -1;
688       //Hide labels and fields (Mesh and Geometry)
689       myDlg->setObjectShown( SMESHGUI_MeshDlg::Mesh, false );
690       myDlg->setObjectShown( SMESHGUI_MeshDlg::Geom, false );
691       myDlg->adjustSize();
692       readMesh();
693     }
694     int curIndex = myDlg->currentMeshType( );
695     QStringList TypeMeshList;
696     createMeshTypeList( TypeMeshList );
697     setAvailableMeshType( TypeMeshList );
698     curIndex =( curIndex >= TypeMeshList.count() ) ? 0 : curIndex;
699     myDlg->setCurrentMeshType( curIndex );
700     setFilteredAlgoData( myMaxShapeDim, curIndex);
701   }
702   catch ( const SALOME::SALOME_Exception& S_ex )
703   {
704     SalomeApp_Tools::QtCatchCorbaException( S_ex );
705   }
706   catch ( ... )
707   {
708   }
709 }
710
711 //================================================================================
712 /*!
713  * \brief Verifies validity of input data
714   * \param theMess - Output parameter intended for returning error message
715   * \retval bool  - TRUE if input data is valid, false otherwise
716  *
717  * Verifies validity of input data. This method is called when "Apply" or "OK" button
718  * is pressed before mesh creation or editing.
719  */
720 //================================================================================
721 bool SMESHGUI_MeshOp::isValid( QString& theMess ) const
722 {
723   // Selected object to be  edited
724   if ( !myToCreate && myDlg->selectedObject( SMESHGUI_MeshDlg::Obj ) == "" )
725   {
726     theMess = tr( "THERE_IS_NO_OBJECT_FOR_EDITING" );
727     return false;
728   }
729
730   // Name
731   QString aMeshName = myDlg->objectText( SMESHGUI_MeshDlg::Obj ).trimmed();
732   if ( aMeshName.isEmpty() )
733   {
734     theMess = myIsMesh ? tr( "NAME_OF_MESH_IS_EMPTY" ) : tr( "NAME_OF_SUBMESH_IS_EMPTY" );
735     return false;
736   }
737
738 /*  // Imported mesh, if create sub-mesh or edit mesh
739   if ( !myToCreate || ( myToCreate && !myIsMesh ))
740   {
741     QString aMeshEntry = myDlg->selectedObject
742       ( myToCreate ? SMESHGUI_MeshDlg::Mesh : SMESHGUI_MeshDlg::Obj );
743     if ( _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.toLatin1().data() )) {
744       SMESH::SMESH_Mesh_var mesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( pMesh );
745       if ( !mesh->_is_nil() && CORBA::is_nil( mesh->GetShapeToMesh() )) {
746         theMess = tr( "IMPORTED_MESH" );
747         return false;
748       }
749     }
750   }*/
751
752   // Geom
753   if ( myToCreate )
754   {
755     QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
756     if ( aGeomEntry.isEmpty() )
757     {
758       theMess = tr( myIsMesh ?
759                     "GEOMETRY_OBJECT_IS_NOT_DEFINED_MESH" :
760                     "GEOMETRY_OBJECT_IS_NOT_DEFINED_SUBMESH");
761       if ( !myIsMesh )
762         return false;
763       dlg()->show();
764       if ( SUIT_MessageBox::warning( myDlg, tr( "SMESH_WRN_WARNING" ), theMess,
765            SUIT_MessageBox::Yes, SUIT_MessageBox::No ) == SUIT_MessageBox::No )
766       {
767         theMess = "";
768         return false;
769       }
770       return true;
771     }
772     _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.toLatin1().data() );
773     if ( !pGeom || GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() )->_is_nil() )
774     {
775       theMess = tr( "GEOMETRY_OBJECT_IS_NULL" );
776       return false;
777     }
778
779     // Mesh
780     if ( !myIsMesh ) // i.e sub-mesh creation,
781     {
782       QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
783       if ( aMeshEntry == "" )
784       {
785         theMess = tr( "MESH_IS_NOT_DEFINED" );
786         return false;
787       }
788       _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.toLatin1().data() );
789       if ( !pMesh || SMESH::SMESH_Mesh::_narrow( _CAST( SObject,pMesh )->GetObject() )->_is_nil() )
790       {
791         theMess = tr( "MESH_IS_NULL" );
792         return false;
793       }
794       if ( !isSubshapeOk() )
795       {
796         theMess = tr( "INVALID_SUBSHAPE" );
797         return false;
798       }
799     }
800   }
801
802   return true;
803 }
804
805 //================================================================================
806 /*!
807  * \brief check compatibility of the algorithm and another algorithm or hypothesis
808   * \param theAlgoData - algorithm data
809   * \param theHypData - hypothesis data
810   * \param theHypType - hypothesis type
811   * \param theHypTypeName - hypothesis type name, must be provided if 2-nd arg is not algo
812   * \retval bool - check result
813  */
814 //================================================================================
815 static bool isCompatible(const HypothesisData* theAlgoData,
816                          const HypothesisData* theHypData,
817                          const int             theHypType)
818 {
819   if ( !theAlgoData )
820     return true;
821
822   if ( theHypType == SMESHGUI_MeshOp::Algo )
823     return SMESH::IsCompatibleAlgorithm( theAlgoData, theHypData );
824
825   bool isOptional;
826   return ( SMESH::IsAvailableHypothesis( theAlgoData, theHypData->TypeName, isOptional ));
827 }
828
829 //================================================================================
830 /*!
831  * \brief Gets available hypotheses or algorithms
832   * \param theDim - specifies dimension of returned hypotheses/algorifms
833   * \param theHypType - specifies whether algorims or hypotheses or additional ones
834   * are retrieved (possible values are in HypType enumeration)
835   * \param theHyps - Output list of hypotheses' names
836   * \param theAlgoData - to select hypos able to be used by this algo (optional)
837  *
838  * Gets available hypotheses or algorithm in accordance with input parameters
839  */
840 //================================================================================
841 void SMESHGUI_MeshOp::availableHyps( const int       theDim,
842                                      const int       theHypType,
843                                      QStringList&    theHyps,
844                                      THypDataList&   theDataList,
845                                      HypothesisData* theAlgoData ) const
846 {
847   theDataList.clear();
848   theHyps.clear();
849   bool isAlgo = ( theHypType == Algo );
850   bool isAux  = ( theHypType == AddHyp );
851   QStringList aHypTypeNameList = SMESH::GetAvailableHypotheses( isAlgo, theDim, isAux, myIsOnGeometry, !myIsMesh );
852
853   QStringList::const_iterator anIter;
854   for ( anIter = aHypTypeNameList.begin(); anIter != aHypTypeNameList.end(); ++anIter )
855   {
856     HypothesisData* aData = SMESH::GetHypothesisData( *anIter );
857     if ( isCompatible ( theAlgoData, aData, theHypType )) {
858       theDataList.append( aData );
859       theHyps.append( aData->Label );
860     }
861   }
862 }
863
864 //================================================================================
865 /*!
866  * \brief Gets existing hypotheses or algorithms
867  *  \param theDim - specifies dimension of returned hypotheses/algorifms
868  *  \param theHypType - specifies whether algorims or hypotheses or additional ones
869  *  are retrieved (possible values are in HypType enumeration)
870  *  \param theFather - start object for finding ( may be component, mesh, or sub-mesh )
871  *  \param theHyps - output list of names.
872  *  \param theHypVars - output list of variables.
873  *  \param theAlgoData - to select hypos able to be used by this algo (optional)
874  *
875  * Gets existing (i.e. already created) hypotheses or algorithm in accordance with
876  * input parameters
877  */
878 //================================================================================
879 void SMESHGUI_MeshOp::existingHyps( const int       theDim,
880                                     const int       theHypType,
881                                     _PTR(SObject)   theFather,
882                                     QStringList&    theHyps,
883                                     THypList&       theHypList,
884                                     HypothesisData* theAlgoData)
885 {
886   // Clear hypoheses list
887   theHyps.clear();
888   theHypList.clear();
889
890   if ( !theFather )
891     return;
892
893   const bool isAux  = ( theHypType == AddHyp );
894
895   _PTR(SObject)          aHypRoot;
896   _PTR(GenericAttribute) anAttr;
897   _PTR(AttributeName)    aName;
898   _PTR(AttributeIOR)     anIOR;
899
900   bool isMesh = !_CAST( SComponent, theFather );
901   int aPart = -1;
902   if ( isMesh )
903     aPart = theHypType == Algo ? SMESH::Tag_RefOnAppliedAlgorithms : SMESH::Tag_RefOnAppliedHypothesis;
904   else
905     aPart = theHypType == Algo ? SMESH::Tag_AlgorithmsRoot : SMESH::Tag_HypothesisRoot;
906
907   if ( theFather->FindSubObject( aPart, aHypRoot ) )
908   {
909     _PTR(ChildIterator) anIter =
910       SMESH::GetActiveStudyDocument()->NewChildIterator( aHypRoot );
911     for ( ; anIter->More(); anIter->Next() )
912     {
913       _PTR(SObject) anObj = anIter->Value();
914       if ( isMesh ) // i.e. mesh or submesh
915       {
916         _PTR(SObject) aRefObj;
917         if ( anObj->ReferencedObject( aRefObj ) )
918           anObj = aRefObj;
919         else
920           continue;
921       }
922       if ( anObj->FindAttribute( anAttr, "AttributeName" ) )
923       {
924         aName = anAttr;
925         CORBA::Object_var aVar = _CAST(SObject,anObj)->GetObject();
926         if ( !CORBA::is_nil( aVar ) )
927         {
928           SMESH::SMESH_Hypothesis_var aHypVar = SMESH::SMESH_Hypothesis::_narrow( aVar );
929           if ( !aHypVar->_is_nil() )
930           {
931             CORBA::String_var hypType = aHypVar->GetName();
932             HypothesisData* aData = SMESH::GetHypothesisData( hypType.in() );
933             if ( !aData) continue;
934             if ( ( theDim == -1 || aData->Dim.contains( theDim ) ) &&
935                  ( isCompatible ( theAlgoData, aData, theHypType )) &&
936                  ( theHypType == Algo || isAux == aData->IsAuxOrNeedHyp ))
937             {
938               std::string aHypName = aName->Value();
939               theHyps.append( aHypName.c_str() );
940               theHypList.append( THypItem( aHypVar, aHypName.c_str() ) );
941             }
942           }
943         }
944       }
945     }
946   }
947 }
948
949 //================================================================================
950 /*!
951  * \brief If create or edit a submesh, return a hypothesis holding parameters used
952  *        to mesh a sub-shape
953   * \param aHypType - The hypothesis type name
954   * \param aServerLib - Server library name
955   * \param hypData - The structure holding the hypothesis type etc.
956   * \retval SMESH::SMESH_Hypothesis_var - the hypothesis holding parameter values
957  */
958 //================================================================================
959 SMESH::SMESH_Hypothesis_var
960 SMESHGUI_MeshOp::getInitParamsHypothesis( const QString& aHypType,
961                                           const QString& aServerLib ) const
962 {
963   if ( aHypType.isEmpty() || aServerLib.isEmpty() )
964     return SMESH::SMESH_Hypothesis::_nil();
965
966   const int nbColonsInMeshEntry = 3;
967   bool isSubMesh = myToCreate ?
968     !myIsMesh :
969     myDlg->selectedObject( SMESHGUI_MeshDlg::Obj ).count(':') > nbColonsInMeshEntry;
970
971   // get mesh and geom object
972   SMESH::SMESH_Mesh_var aMeshVar = SMESH::SMESH_Mesh::_nil();
973   GEOM::GEOM_Object_var aGeomVar = GEOM::GEOM_Object::_nil();
974
975   QString anEntry;
976   if ( isSubMesh )
977   {
978     anEntry = myDlg->selectedObject
979       ( myToCreate ? SMESHGUI_MeshDlg::Mesh : SMESHGUI_MeshDlg::Obj );
980     if ( _PTR(SObject) pObj = studyDS()->FindObjectID( anEntry.toLatin1().data() ))
981     {
982       CORBA::Object_ptr Obj = _CAST( SObject,pObj )->GetObject();
983       if ( myToCreate ) // mesh and geom may be selected
984       {
985         aMeshVar = SMESH::SMESH_Mesh::_narrow( Obj );
986         anEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
987         if ( _PTR(SObject) pGeom = studyDS()->FindObjectID( anEntry.toLatin1().data() ))
988           aGeomVar= GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
989       }
990       else // edition: sub-mesh may be selected
991       {
992         SMESH::SMESH_subMesh_var sm = SMESH::SMESH_subMesh::_narrow( Obj );
993         if ( !sm->_is_nil() ) {
994           aMeshVar = sm->GetFather();
995           aGeomVar = sm->GetSubShape();
996         }
997       }
998     }
999   }
1000   else // mesh
1001   {
1002     if ( !myToCreate ) // mesh to edit can be selected
1003     {
1004       anEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
1005       if ( _PTR(SObject) pMesh = studyDS()->FindObjectID( anEntry.toLatin1().data() ))
1006       {
1007         aMeshVar = SMESH::SMESH_Mesh::_narrow( _CAST( SObject,pMesh )->GetObject() );
1008         if ( !aMeshVar->_is_nil() )
1009           aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pMesh );
1010       }
1011     }
1012     if ( aGeomVar->_is_nil() ) {
1013       anEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
1014       if ( _PTR(SObject) pGeom = studyDS()->FindObjectID( anEntry.toLatin1().data() ))
1015       {
1016         aGeomVar= GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
1017       }
1018     }
1019   }
1020
1021   SMESH::SMESH_Hypothesis_var hyp =
1022     SMESHGUI::GetSMESHGen()->GetHypothesisParameterValues( aHypType.toLatin1().data(),
1023                                                            aServerLib.toLatin1().data(),
1024                                                            aMeshVar,
1025                                                            aGeomVar,
1026                                                            /*byMesh = */isSubMesh);
1027   if ( hyp->_is_nil() && isSubMesh )
1028     hyp = SMESHGUI::GetSMESHGen()->GetHypothesisParameterValues( aHypType.toLatin1().data(),
1029                                                                  aServerLib.toLatin1().data(),
1030                                                                  aMeshVar,
1031                                                                  aGeomVar,
1032                                                                  /*byMesh = */false);
1033   return hyp;
1034 }
1035
1036 //================================================================================
1037 /*!
1038  * \brief initialize a hypothesis creator
1039  */
1040 //================================================================================
1041
1042 void SMESHGUI_MeshOp::initHypCreator( SMESHGUI_GenericHypothesisCreator* theCreator )
1043 {
1044   if ( !theCreator ) return;
1045
1046   // Set shapes, of mesh and sub-mesh if any
1047
1048   // get Entry of the Geom object
1049   QString aGeomEntry = "";
1050   QString aMeshEntry = "";
1051   QString anObjEntry = "";
1052   aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
1053   aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
1054   anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
1055
1056   if ( myToCreate && myIsMesh )
1057     aMeshEntry = aGeomEntry;
1058
1059   if ( aMeshEntry != aGeomEntry ) { // Get Geom object from Mesh of a sub-mesh being edited
1060     _PTR(SObject) pObj = studyDS()->FindObjectID( aMeshEntry.toLatin1().data() );
1061     GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj );
1062     aMeshEntry = ( aGeomVar->_is_nil() ) ? QString() : SMESH::toQStr( aGeomVar->GetStudyEntry() );
1063   }
1064
1065   if ( aMeshEntry == "" && aGeomEntry == "" ) { // get geom of an object being edited
1066     _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.toLatin1().data() );
1067     bool isMesh;
1068     GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj, &isMesh );
1069     if ( !aGeomVar->_is_nil() )
1070     {
1071       aGeomEntry = SMESH::toQStr( aGeomVar->GetStudyEntry() );
1072       if ( isMesh )
1073         aMeshEntry = aGeomEntry;
1074     }
1075   }
1076
1077   if ( anObjEntry != "" && aGeomEntry != "" && aMeshEntry == "" ) {
1078     // take geometry from submesh being created
1079     _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.toLatin1().data() );
1080     if ( pObj ) {
1081       // if current object is sub-mesh
1082       SMESH::SMESH_subMesh_var aSubMeshVar =
1083         SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() );
1084       if ( !aSubMeshVar->_is_nil() ) {
1085         SMESH::SMESH_Mesh_var aMeshVar =  aSubMeshVar->GetFather();
1086         if ( !aMeshVar->_is_nil() ) {
1087           _PTR(SObject) aMeshSO = SMESH::FindSObject( aMeshVar );
1088           GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( aMeshSO );
1089           if ( !aGeomVar->_is_nil() )
1090             aMeshEntry = SMESH::toQStr( aGeomVar->GetStudyEntry() );
1091         }
1092       }
1093     }
1094   }
1095
1096   theCreator->setShapeEntry( aGeomEntry );
1097   if ( aMeshEntry != "" )
1098     theCreator->setMainShapeEntry( aMeshEntry );
1099 }
1100
1101 //================================================================================
1102 /*!
1103  * \Brief Returns tab dimention
1104   * \param tab - the tab in the dlg
1105   * \param dlg - my dialogue
1106   * \retval int - dimention
1107  */
1108 //================================================================================
1109 static int getTabDim (const QObject* tab, SMESHGUI_MeshDlg* dlg )
1110 {
1111   int aDim = -1;
1112   for (int i = SMESH::DIM_0D; i <= SMESH::DIM_3D; i++)
1113     if (tab == dlg->tab(i))
1114       aDim = i;
1115   return aDim;
1116 }
1117
1118 //================================================================================
1119 /*!
1120  * \brief Create hypothesis
1121   * \param theHypType - hypothesis category (main or additional)
1122   * \param theIndex - index of type of hypothesis to be cerated
1123  *
1124  * Specifies dimension of hypothesis to be created (using sender() method),
1125  * specifies its type and calls method for hypothesis creation
1126  */
1127 //================================================================================
1128 void SMESHGUI_MeshOp::onCreateHyp( const int theHypType, const int theIndex )
1129 {
1130   // Specifies dimension of hypothesis to be created
1131   int aDim = getTabDim( sender(), myDlg );
1132   if (aDim == -1)
1133     return;
1134
1135   // Specifies type of hypothesis to be created
1136   THypDataList& dataList = myAvailableHypData[ aDim ][ theHypType ];
1137   if (theIndex < 0 || theIndex >= dataList.count())
1138     return;
1139   QString aHypTypeName = dataList[ theIndex ]->TypeName;
1140
1141   // Create hypothesis
1142   createHypothesis(aDim, theHypType, aHypTypeName);
1143 }
1144
1145 namespace
1146 {
1147   QString GetUniqueName (const QStringList& theHypNames,
1148                          const QString& theName,
1149                          size_t theIteration = 1)
1150   {
1151     QString aName = theName + "_" + QString::number( theIteration );
1152     if ( theHypNames.contains( aName ) )
1153       return GetUniqueName( theHypNames, theName, ++theIteration );
1154     return aName;
1155   }
1156 }
1157
1158 //================================================================================
1159 /*!
1160  *  Create hypothesis and update dialog.
1161  *  \param theDim - dimension of hypothesis to be created
1162  *  \param theType - hypothesis category (algorithm, hypothesis, additional hypothesis)
1163  *  \param theTypeName - specifies hypothesis to be created
1164  */
1165 //================================================================================
1166 void SMESHGUI_MeshOp::createHypothesis(const int theDim,
1167                                        const int theType,
1168                                        const QString& theTypeName)
1169 {
1170   HypothesisData* aData = SMESH::GetHypothesisData(theTypeName);
1171   if (!aData)
1172     return;
1173
1174   myDim = theDim;
1175   myType = theType;
1176   QStringList aHypNames;
1177   TDim2Type2HypList::const_iterator aDimIter = myExistingHyps.begin();
1178   for ( ; aDimIter != myExistingHyps.end(); aDimIter++) {
1179     const TType2HypList& aType2HypList = aDimIter.value();
1180     TType2HypList::const_iterator aTypeIter = aType2HypList.begin();
1181     for ( ; aTypeIter != aType2HypList.end(); aTypeIter++) {
1182       const THypList& aHypList = aTypeIter.value();
1183       THypList::const_iterator anIter = aHypList.begin();
1184       for ( ; anIter != aHypList.end(); anIter++) {
1185         const THypItem& aHypItem = *anIter;
1186         const QString& aHypName = aHypItem.second;
1187         aHypNames.append(aHypName);
1188       }
1189     }
1190   }
1191   QString aHypName = GetUniqueName( aHypNames, aData->Label);
1192
1193   // existing hypos
1194   bool dialog = false;
1195
1196   QString aClientLibName = aData->ClientLibName;
1197   if (aClientLibName == "") {
1198     // Call hypothesis creation server method (without GUI)
1199     SMESH::SMESH_Hypothesis_var aHyp =
1200       SMESH::CreateHypothesis(theTypeName, aHypName, false);
1201     aHyp.out();
1202   }
1203   else {
1204     // Get hypotheses creator client (GUI)
1205     SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator(theTypeName);
1206
1207     // Create hypothesis
1208     if (aCreator)
1209     {
1210       // Get parameters appropriate to initialize a new hypothesis
1211       SMESH::SMESH_Hypothesis_var initParamHyp =
1212         getInitParamsHypothesis(theTypeName, aData->ServerLibName);
1213
1214       removeCustomFilters(); // Issue 0020170
1215
1216       // set shapes, of mesh and sub-mesh if any
1217       initHypCreator( aCreator );
1218
1219       myDlg->setEnabled( false );
1220       aCreator->create(initParamHyp, aHypName, myDlg, this, SLOT( onHypoCreated( int ) ) );
1221       dialog = true;
1222     }
1223     else {
1224      SMESH::SMESH_Hypothesis_var aHyp =
1225        SMESH::CreateHypothesis(theTypeName, aHypName, false);
1226      aHyp.out();
1227     }
1228   }
1229
1230   if( !dialog )
1231     onHypoCreated(2);
1232 }
1233
1234 //================================================================================
1235 /*!
1236  *  Necessary steps after hypothesis creation
1237  *  \param result - creation result:
1238  *   0 = rejected
1239  *   1 = accepted
1240  *   2 = additional value meaning that slot is called not from dialog box
1241  */
1242 //================================================================================
1243 void SMESHGUI_MeshOp::onHypoCreated( int result )
1244 {
1245   if( result != 2 )
1246   {
1247     int obj = myDlg->getActiveObject();
1248     onActivateObject( obj ); // Issue 0020170. Restore filters
1249     myDlg->setEnabled( true );
1250   }
1251
1252   _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent("SMESH");
1253
1254   int nbHyp = myExistingHyps[myDim][myType].count();
1255   HypothesisData* algoData = hypData( myDim, Algo, currentHyp( myDim, Algo ));
1256   QStringList aNewHyps;
1257   existingHyps(myDim, myType, aFather, aNewHyps, myExistingHyps[myDim][myType], algoData);
1258   if (aNewHyps.count() > nbHyp)
1259   {
1260     for (int i = nbHyp; i < aNewHyps.count(); i++)
1261       myDlg->tab(myDim)->addHyp(myType, aNewHyps[i]);
1262   }
1263
1264   if( result!=2 && myHypoSet )
1265     processSet();
1266 }
1267
1268 //================================================================================
1269 /*!
1270  * \brief Calls plugin methods for hypothesis editing
1271   * \param theHypType - specifies whether main hypothesis or additional one
1272   * is edited
1273   * \param theIndex - index of existing hypothesis
1274  *
1275  * Calls plugin methods for hypothesis editing
1276  */
1277 //================================================================================
1278 void SMESHGUI_MeshOp::onEditHyp( const int theHypType, const int theIndex )
1279 {
1280   // Speicfies dimension of hypothesis to be created
1281   int aDim = getTabDim( sender(), myDlg );
1282   if (aDim == -1)
1283     return;
1284
1285   const THypList& aList = myExistingHyps[ aDim ][ theHypType ];
1286   if ( theIndex < 0 || theIndex >= aList.count() )
1287     return;
1288   const THypItem& aHypItem = aList[ theIndex ];
1289   SMESH::SMESH_Hypothesis_var aHyp = aHypItem.first;
1290   if ( aHyp->_is_nil() )
1291     return;
1292
1293   SMESHGUI_GenericHypothesisCreator* aCreator =
1294     SMESH::GetHypothesisCreator( SMESH::toQStr( aHyp->GetName() ));
1295   if ( aCreator )
1296   {
1297     // set initial parameters
1298     SMESH::SMESH_Hypothesis_var initParamHyp =
1299       getInitParamsHypothesis( SMESH::toQStr( aHyp->GetName() ),
1300                                SMESH::toQStr( aHyp->GetLibName() ));
1301     aCreator->setInitParamsHypothesis( initParamHyp );
1302
1303     // set shapes, of mesh and sub-mesh if any
1304     initHypCreator( aCreator );
1305
1306     removeCustomFilters(); // Issue 0020170
1307     myDlg->setEnabled( false );
1308
1309     aCreator->edit( aHyp.in(), aHypItem.second, dlg(), this, SLOT( onHypoEdited( int ) ) );
1310   }
1311 }
1312
1313 //================================================================================
1314 /*!
1315  *  Necessary steps after hypothesis edition
1316  *  \param result - creation result:
1317  *   0 = rejected
1318  *   1 = accepted
1319  */
1320 //================================================================================
1321 void SMESHGUI_MeshOp::onHypoEdited( int result )
1322 {
1323   int obj = myDlg->getActiveObject();
1324   onActivateObject( obj ); // Issue 0020170. Restore filters
1325   myDlg->setEnabled( true );
1326 }
1327
1328 //================================================================================
1329 /*!
1330  * \brief access to hypothesis data
1331   * \param theDim - hyp dimension
1332   * \param theHypType - hyp type (Algo,MainHyp or AddHyp)
1333   * \param theIndex - index in the list
1334   * \retval HypothesisData* - result data, may be 0
1335  */
1336 //================================================================================
1337 HypothesisData* SMESHGUI_MeshOp::hypData( const int theDim,
1338                                           const int theHypType,
1339                                           const int theIndex)
1340 {
1341   if ( theDim     > -1 && theDim    <= SMESH::DIM_3D &&
1342        theHypType > -1 && theHypType < NbHypTypes &&
1343        theIndex   > -1 && theIndex   < myAvailableHypData[ theDim ][ theHypType ].count() )
1344     return myAvailableHypData[ theDim ][ theHypType ][ theIndex ];
1345   return 0;
1346 }
1347
1348 //================================================================================
1349 /*!
1350  * \brief Set available algos and hypos according to the selected algorithm
1351   * \param theIndex - algorithm index
1352  */
1353 //================================================================================
1354 void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
1355                                       const int theDim )
1356 {
1357   if ( myIgnoreAlgoSelection )
1358     return;
1359
1360   int aDim = theDim < 0 ? getTabDim( sender(), myDlg ): theDim;
1361   if (aDim == -1)
1362     return;
1363
1364   // find highest available dimension, all algos of this dimension are available for choice
1365   int aTopDim = -1;
1366   for (int i = SMESH::DIM_0D; i <= SMESH::DIM_3D; i++)
1367     if (isAccessibleDim( i ))
1368       aTopDim = i;
1369   if (aTopDim == -1)
1370     return;
1371
1372   const bool isSubmesh = ( myToCreate ? !myIsMesh : myDlg->isObjectShown( SMESHGUI_MeshDlg::Mesh ));
1373
1374   HypothesisData* algoData = hypData( aDim, Algo, theIndex );
1375   HypothesisData* algoByDim[4];
1376   algoByDim[ aDim ] = algoData;
1377
1378   QStringList anAvailable;
1379
1380   // check that tab enabled of one less dimension
1381   if ( aDim > SMESH::DIM_0D )
1382   {
1383     if ( isAccessibleDim( aDim - 1 ) )
1384     {
1385       if (( myDlg->currentMeshType() != MT_ANY ) &&
1386           ( !algoData || ( myIsOnGeometry && algoData->InputTypes.isEmpty() )))
1387         for (int i = aDim - 1; i >= SMESH::DIM_0D; i--)
1388           if ( isAccessibleDim( i ) ) {
1389             myDlg->disableTab( i );
1390             setCurrentHyp(i, Algo, -1);
1391           }
1392     }
1393     else if ( algoData && myIsOnGeometry && !algoData->InputTypes.isEmpty() )
1394     {
1395       myDlg->enableTab( aDim - 1 );
1396     }
1397   }
1398
1399   // check that algorithms of other dimentions are compatible with
1400   // the selected one
1401   if ( !algoData ) { // all algos becomes available
1402     if (myDlg->currentMeshType() == MT_ANY || aDim == SMESH::DIM_1D || aDim == SMESH::DIM_0D)
1403       availableHyps( aDim, Algo, anAvailable, myAvailableHypData[ aDim ][ Algo ]);
1404     else{
1405       anAvailable.clear();
1406       for (int i = 0; i < myFilteredAlgoData[aDim].count(); ++i) {
1407         HypothesisData* aCurAlgo = myFilteredAlgoData[aDim][ i ];
1408         anAvailable.append( aCurAlgo->Label );
1409       }
1410     }
1411     myDlg->tab( aDim )->setAvailableHyps( Algo, anAvailable );
1412   }
1413   // 2 loops: backward and forward from algo dimension
1414   for ( int forward = false; forward <= true; ++forward )
1415   {
1416     int dim = aDim + 1, lastDim = SMESH::DIM_3D, dir = 1;
1417     if ( !forward ) {
1418       dim = aDim - 1; lastDim = SMESH::DIM_0D; dir = -1;
1419     }
1420     HypothesisData* prevAlgo = algoData;
1421     bool noCompatible = false;
1422     for ( ; dim * dir <= lastDim * dir; dim += dir)
1423     {
1424       if ( !isAccessibleDim( dim ))
1425         continue;
1426       if ( noCompatible ) { // the selected algo has no compatible ones
1427         anAvailable.clear();
1428         myDlg->tab( dim )->setAvailableHyps( Algo, anAvailable );
1429         myAvailableHypData[dim][Algo].clear();
1430         algoByDim[ dim ] = 0;
1431         continue;
1432       }
1433       // get currently selected algo
1434       int algoIndex = currentHyp( dim, Algo );
1435       HypothesisData* curAlgo = hypData( dim, Algo, algoIndex );
1436       if ( curAlgo ) { // some algo selected
1437         if ( !isCompatible( prevAlgo, curAlgo, Algo ))
1438           curAlgo = 0;
1439       }
1440       // set new available algoritms
1441       if (myDlg->currentMeshType() == MT_ANY || dim == SMESH::DIM_1D || dim == SMESH::DIM_0D)
1442         availableHyps( dim, Algo, anAvailable, myAvailableHypData[dim][Algo], prevAlgo );
1443       else{
1444         anAvailable.clear();
1445         myAvailableHypData[dim][Algo].clear();
1446         for (int i = 0; i < myFilteredAlgoData[dim].count(); ++i) {
1447           HypothesisData* aCurAlgo = myFilteredAlgoData[dim][ i ];
1448           if ( isCompatible ( prevAlgo, aCurAlgo, Algo )) {
1449             anAvailable.append( aCurAlgo->Label );
1450             myAvailableHypData[dim][Algo].append( aCurAlgo );
1451           }
1452         }
1453       }
1454       HypothesisData* soleCompatible = 0;
1455       if ( anAvailable.count() == 1 )
1456         soleCompatible = myAvailableHypData[dim][Algo][0];
1457       if ( dim == aTopDim && prevAlgo ) {// all available algoritms should be selectable any way
1458         if (myDlg->currentMeshType() == MT_ANY)
1459           availableHyps( dim, Algo, anAvailable, myAvailableHypData[dim][Algo], 0 );
1460       }
1461       myDlg->tab( dim )->setAvailableHyps( Algo, anAvailable );
1462       noCompatible = anAvailable.isEmpty();
1463
1464       // restore previously selected algo
1465       algoIndex = myAvailableHypData[dim][Algo].indexOf( curAlgo );
1466       if ( !isSubmesh && algoIndex < 0 && soleCompatible && !forward && dim != SMESH::DIM_0D)
1467         // select the sole compatible algo
1468         algoIndex = myAvailableHypData[dim][Algo].indexOf( soleCompatible );
1469       setCurrentHyp( dim, Algo, algoIndex);
1470
1471       // remember current algo
1472       prevAlgo = algoByDim[ dim ] = hypData( dim, Algo, algoIndex );
1473     }
1474   }
1475
1476   // set hypotheses corresponding to the found algoritms
1477
1478   _PTR(SObject) pObj = SMESH::GetActiveStudyDocument()->FindComponent("SMESH");
1479
1480   for ( int dim = SMESH::DIM_0D; dim <= SMESH::DIM_3D; dim++ )
1481   {
1482     if ( !isAccessibleDim( dim ))
1483       continue;
1484     for ( int type = MainHyp; type < NbHypTypes; type++ )
1485     {
1486       myAvailableHypData[ dim ][ type ].clear();
1487       QStringList anAvailable, anExisting;
1488
1489       HypothesisData* curAlgo = algoByDim[ dim ];
1490       int hypIndex = currentHyp( dim, type );
1491
1492       SMESH::SMESH_Hypothesis_var curHyp;
1493       if ( hypIndex >= 0 && hypIndex < myExistingHyps[ dim ][ type ].count() )
1494         curHyp = myExistingHyps[ dim ][ type ][ hypIndex ].first;
1495
1496       if ( !myToCreate && !curAlgo && !curHyp->_is_nil() ) { // edition, algo not selected
1497         // try to find algo by selected hypothesis in order to keep it selected
1498         bool algoDeselectedByUser = ( theDim < 0 && aDim == dim );
1499         QString curHypType = SMESH::toQStr( curHyp->GetName() );
1500         if ( !algoDeselectedByUser &&
1501              myObjHyps[ dim ][ type ].count() > 0 &&
1502              curHypType == SMESH::toQStr( myObjHyps[ dim ][ type ].first().first->GetName()) )
1503         {
1504           HypothesisData* hypData = SMESH::GetHypothesisData( curHyp->GetName() );
1505           for (int i = 0; i < myAvailableHypData[ dim ][ Algo ].count(); ++i) {
1506             curAlgo = myAvailableHypData[ dim ][ Algo ][ i ];
1507             if (curAlgo && hypData && isCompatible(curAlgo, hypData, type))
1508               break;
1509             else
1510               curAlgo = 0;
1511           }
1512         }
1513       }
1514       // get hyps compatible with curAlgo
1515       bool defaulHypAvlbl = false;
1516       if ( curAlgo )
1517       {
1518         // check if a selected hyp is compatible with the curAlgo
1519         if ( !curHyp->_is_nil() ) {
1520           HypothesisData* hypData = SMESH::GetHypothesisData( curHyp->GetName() );
1521           if ( !isCompatible( curAlgo, hypData, type ))
1522             curHyp = SMESH::SMESH_Hypothesis::_nil();
1523         }
1524         existingHyps( dim, type, pObj, anExisting, myExistingHyps[ dim ][ type ], curAlgo);
1525         availableHyps( dim, type, anAvailable, myAvailableHypData[ dim ][ type ], curAlgo);
1526         defaulHypAvlbl = (type == MainHyp && !curAlgo->IsAuxOrNeedHyp );
1527       }
1528       // set list of hypotheses
1529       myDlg->tab( dim )->setAvailableHyps( type, anAvailable );
1530       myDlg->tab( dim )->setExistingHyps( type, anExisting, defaulHypAvlbl );
1531
1532       // set current existing hypothesis
1533       if ( !curHyp->_is_nil() && !anExisting.isEmpty() )
1534         hypIndex = this->find( curHyp, myExistingHyps[ dim ][ type ]);
1535       else
1536         hypIndex = -1;
1537       if ( !isSubmesh && hypIndex < 0 && anExisting.count() == 1 ) {
1538         // none is yet selected => select the sole existing if it is not optional
1539         CORBA::String_var hypTypeName = myExistingHyps[ dim ][ type ].first().first->GetName();
1540         bool isOptional = true;
1541         if ( algoByDim[ dim ] &&
1542             SMESH::IsAvailableHypothesis( algoByDim[ dim ], hypTypeName.in(), isOptional ) &&
1543             !isOptional )
1544           hypIndex = 0;
1545       }
1546       setCurrentHyp( dim, type, hypIndex );
1547     }
1548   }
1549 }
1550
1551 //================================================================================
1552 /*!
1553  * \brief Creates and selects hypothesis of hypotheses set
1554  * \param theSetName - The name of hypotheses set
1555  */
1556 //================================================================================
1557 void SMESHGUI_MeshOp::onHypoSet( const QString& theSetName )
1558 {
1559   myHypoSet = SMESH::GetHypothesesSet(theSetName);
1560   if (!myHypoSet)
1561     return;
1562
1563   // clear all hyps
1564   for (int dim = SMESH::DIM_0D; dim <= SMESH::DIM_3D; dim++) {
1565     setCurrentHyp(dim, Algo, -1);
1566     setCurrentHyp(dim, AddHyp, -1);
1567     setCurrentHyp(dim, MainHyp, -1);
1568   }
1569
1570   myHypoSet->init(true); //algorithms
1571   processSet();
1572   myHypoSet->init(false); //hypotheses
1573   processSet();
1574   myHypoSet = 0;
1575 }
1576
1577 //================================================================================
1578 /*!
1579  * \brief One step of hypothesis/algorithm list creation
1580  *
1581  * Creates a hypothesis or an algorithm for current item of internal list of names myHypoSet
1582  */
1583 //================================================================================
1584 void SMESHGUI_MeshOp::processSet()
1585 {
1586   myHypoSet->next();
1587   if( !myHypoSet->more() )
1588     return;
1589
1590   bool isAlgo = myHypoSet->isAlgo();
1591   QString aHypoTypeName = myHypoSet->current();
1592   HypothesisData* aHypData = SMESH::GetHypothesisData(aHypoTypeName);
1593   if (!aHypData)
1594   {
1595     processSet();
1596     return;
1597   }
1598
1599   int aDim = aHypData->Dim[0];
1600   // create or/and set
1601   if (isAlgo)
1602   {
1603     int index = myAvailableHypData[aDim][Algo].indexOf( aHypData );
1604     if ( index < 0 )
1605     {
1606       QStringList anAvailable;
1607       availableHyps( aDim, Algo, anAvailable, myAvailableHypData[aDim][Algo] );
1608       myDlg->tab( aDim )->setAvailableHyps( Algo, anAvailable );
1609       index = myAvailableHypData[aDim][Algo].indexOf( aHypData );
1610     }
1611     setCurrentHyp( aDim, Algo, index );
1612     onAlgoSelected( index, aDim );
1613     processSet();
1614   }
1615   else
1616   {
1617     bool mainHyp = true;
1618     QStringList anAvailable;
1619     availableHyps( aDim, MainHyp, anAvailable, myAvailableHypData[aDim][MainHyp] );
1620     myDlg->tab( aDim )->setAvailableHyps( MainHyp, anAvailable );
1621     int index = myAvailableHypData[aDim][MainHyp].indexOf( aHypData );
1622     if ( index < 0 )
1623     {
1624       mainHyp = false;
1625       index = myAvailableHypData[aDim][AddHyp].indexOf( aHypData );
1626     }
1627     if (index >= 0)
1628       createHypothesis(aDim, mainHyp ? MainHyp : AddHyp, aHypoTypeName);
1629     else
1630       processSet();
1631   }
1632 }
1633
1634 //================================================================================
1635 /*!
1636  * \brief Creates mesh
1637   * \param theMess - Output parameter intended for returning error message
1638   * \param theEntryList - List of entries of published objects
1639   * \retval bool  - TRUE if mesh is created, FALSE otherwise
1640  *
1641  * Creates mesh
1642  */
1643 //================================================================================
1644 bool SMESHGUI_MeshOp::createMesh( QString& theMess, QStringList& theEntryList )
1645 {
1646   theMess = "";
1647
1648   QStringList aList;
1649   myDlg->selectedObject( SMESHGUI_MeshDlg::Geom, aList );
1650   if ( aList.isEmpty() )
1651   {
1652     SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen();
1653     if ( aSMESHGen->_is_nil() )
1654       return false;
1655
1656     SMESH::SMESH_Mesh_var aMeshVar= aSMESHGen->CreateEmptyMesh();
1657     if ( aMeshVar->_is_nil() )
1658       return false;
1659
1660     _PTR(SObject) aMeshSO = SMESH::FindSObject( aMeshVar.in() );
1661     if ( aMeshSO ) {
1662       SMESH::SetName( aMeshSO, myDlg->objectText( SMESHGUI_MeshDlg::Obj ) );
1663       theEntryList.append( aMeshSO->GetID().c_str() );
1664     }
1665     return true;
1666   }
1667   QString namePrefix;
1668   if ( aList.count() > 1 )
1669   {
1670     namePrefix = myDlg->objectText( SMESHGUI_MeshDlg::Obj );
1671     int i = namePrefix.length() - 1;
1672     while ( i > 0 && namePrefix[i].isDigit() )
1673       --i;
1674     if ( i < namePrefix.length() - 1 )
1675       namePrefix.chop( namePrefix.length() - 1 - i );
1676     else
1677       namePrefix += "_";
1678   }
1679   QStringList::Iterator it = aList.begin();
1680   for ( int i = 0; it!=aList.end(); it++, ++i )
1681   {
1682     QString aGeomEntry = *it;
1683     _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.toLatin1().data() );
1684     GEOM::GEOM_Object_var aGeomVar =
1685       GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
1686
1687     SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen();
1688     if ( aSMESHGen->_is_nil() )
1689       return false;
1690
1691     SUIT_OverrideCursor aWaitCursor;
1692
1693     // create mesh
1694     SMESH::SMESH_Mesh_var aMeshVar = aSMESHGen->CreateMesh( aGeomVar );
1695     if ( aMeshVar->_is_nil() )
1696       return false;
1697     _PTR(SObject) aMeshSO = SMESH::FindSObject( aMeshVar.in() );
1698     if ( aMeshSO ) {
1699       theEntryList.append( aMeshSO->GetID().c_str() );
1700       if ( i > 0 ) setDefaultName( namePrefix );
1701       SMESH::SetName( aMeshSO, myDlg->objectText( SMESHGUI_MeshDlg::Obj ) );
1702     }
1703
1704     for ( int aDim = SMESH::DIM_0D; aDim <= SMESH::DIM_3D; aDim++ ) {
1705       if ( !isAccessibleDim( aDim )) continue;
1706
1707       // assign hypotheses
1708       for ( int aHypType = MainHyp; aHypType <= AddHyp; aHypType++ ) {
1709         int aHypIndex = currentHyp( aDim, aHypType );
1710         if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() ) {
1711           SMESH::SMESH_Hypothesis_var aHypVar = myExistingHyps[ aDim ][ aHypType ][ aHypIndex ].first;
1712           if ( !aHypVar->_is_nil() )
1713             SMESH::AddHypothesisOnMesh( aMeshVar, aHypVar );
1714         }
1715       }
1716       // find or create algorithm
1717       SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( aDim );
1718       if ( !anAlgoVar->_is_nil() )
1719         SMESH::AddHypothesisOnMesh( aMeshVar, anAlgoVar );
1720     }
1721   }
1722   return true;
1723 }
1724
1725 //================================================================================
1726 /*!
1727  * \brief Creates sub-mesh
1728   * \param theMess - Output parameter intended for returning error message
1729   * \param theEntryList - List of entries of published objects
1730   * \retval bool  - TRUE if sub-mesh is created, FALSE otherwise
1731  *
1732  * Creates sub-mesh
1733  */
1734 //================================================================================
1735 bool SMESHGUI_MeshOp::createSubMesh( QString& theMess, QStringList& theEntryList )
1736 {
1737   theMess = "";
1738
1739   SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen();
1740   if ( aSMESHGen->_is_nil() )
1741     return false;
1742
1743   // get mesh object
1744   QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
1745   _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.toLatin1().data() );
1746   SMESH::SMESH_Mesh_var aMeshVar =
1747     SMESH::SMESH_Mesh::_narrow( _CAST( SObject,pMesh )->GetObject() );
1748   if (aMeshVar->_is_nil())
1749     return false;
1750
1751   // GEOM shape of the main mesh
1752   GEOM::GEOM_Object_var mainGeom = aMeshVar->GetShapeToMesh();
1753
1754   // Name for the new sub-mesh
1755   QString aName = myDlg->objectText(SMESHGUI_MeshDlg::Obj);
1756
1757   // get geom object
1758   GEOM::GEOM_Object_var aGeomVar;
1759   QStringList aGEOMs;
1760   myDlg->selectedObject(SMESHGUI_MeshDlg::Geom, aGEOMs);
1761   if (aGEOMs.count() == 1)
1762   {
1763     //QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
1764     QString aGeomEntry = aGEOMs.first();
1765     _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.toLatin1().data() );
1766     aGeomVar = GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
1767   }
1768   else if (aGEOMs.count() > 1)
1769   {
1770     // create a GEOM group
1771     GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen();
1772     _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
1773     if (!geomGen->_is_nil() && aStudy) {
1774       GEOM::GEOM_IGroupOperations_wrap op =
1775         geomGen->GetIGroupOperations(aStudy->StudyId());
1776       if (!op->_is_nil()) {
1777         // check and add all selected GEOM objects: they must be
1778         // a sub-shapes of the main GEOM and must be of one type
1779         int iSubSh = 0;
1780         TopAbs_ShapeEnum aGroupType = TopAbs_SHAPE;
1781         GEOM::ListOfGO_var aSeq = new GEOM::ListOfGO;
1782         aSeq->length(aGEOMs.count());
1783         QStringList::const_iterator aSubShapesIter = aGEOMs.begin();
1784         for ( ; aSubShapesIter != aGEOMs.end(); aSubShapesIter++, iSubSh++) {
1785           QString aSubGeomEntry = (*aSubShapesIter);
1786           _PTR(SObject) pSubGeom = studyDS()->FindObjectID(aSubGeomEntry.toLatin1().data());
1787           GEOM::GEOM_Object_var aSubGeomVar =
1788             GEOM::GEOM_Object::_narrow(_CAST(SObject,pSubGeom)->GetObject());
1789           TopAbs_ShapeEnum aSubShapeType = (TopAbs_ShapeEnum)aSubGeomVar->GetShapeType();
1790           if (iSubSh == 0) {
1791             aGroupType = aSubShapeType;
1792           } else {
1793             if (aSubShapeType != aGroupType)
1794               aGroupType = TopAbs_SHAPE;
1795           }
1796           aSeq[iSubSh] = aSubGeomVar;
1797         }
1798         // create a group
1799         GEOM::GEOM_Object_wrap aGroupVar = op->CreateGroup(mainGeom, aGroupType);
1800         op->UnionList(aGroupVar, aSeq);
1801
1802         if (op->IsDone())
1803         {
1804           aGeomVar = GEOM::GEOM_Object::_duplicate( aGroupVar.in() );
1805
1806           // publish the GEOM group in study
1807           QString aNewGeomGroupName ("Auto_group_for_");
1808           aNewGeomGroupName += aName;
1809           SALOMEDS::Study_var aStudyVar = _CAST(Study, aStudy)->GetStudy();
1810           SALOMEDS::SObject_wrap aNewGroupSO =
1811             geomGen->AddInStudy( aStudyVar, aGeomVar,
1812                                  aNewGeomGroupName.toLatin1().data(), mainGeom);
1813         }
1814       }
1815     }
1816   }
1817   else {
1818   }
1819   if (aGeomVar->_is_nil())
1820     return false;
1821
1822   SUIT_OverrideCursor aWaitCursor;
1823
1824   // create sub-mesh
1825   SMESH::SMESH_subMesh_var aSubMeshVar = aMeshVar->GetSubMesh( aGeomVar, aName.toLatin1().data() );
1826   _PTR(SObject) aSubMeshSO = SMESH::FindSObject( aSubMeshVar.in() );
1827   if ( aSubMeshSO ) {
1828     SMESH::SetName( aSubMeshSO, aName.toLatin1().data() );
1829     theEntryList.append( aSubMeshSO->GetID().c_str() );
1830   }
1831
1832   for ( int aDim = SMESH::DIM_0D; aDim <= SMESH::DIM_3D; aDim++ )
1833   {
1834     if ( !isAccessibleDim( aDim )) continue;
1835
1836     // find or create algorithm
1837     SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( aDim );
1838     if ( !anAlgoVar->_is_nil() )
1839       SMESH::AddHypothesisOnSubMesh( aSubMeshVar, anAlgoVar );
1840     // assign hypotheses
1841     for ( int aHypType = MainHyp; aHypType <= AddHyp; aHypType++ )
1842     {
1843       int aHypIndex = currentHyp( aDim, aHypType );
1844       if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() )
1845       {
1846         SMESH::SMESH_Hypothesis_var aHypVar =
1847           myExistingHyps[ aDim ][ aHypType ][ aHypIndex ].first;
1848         if ( !aHypVar->_is_nil() )
1849           SMESH::AddHypothesisOnSubMesh( aSubMeshVar, aHypVar );
1850       }
1851     }
1852   }
1853
1854   // deselect geometry: next submesh should be created on other sub-shape
1855   myDlg->clearSelection( SMESHGUI_MeshDlg::Geom );
1856   selectObject( _PTR(SObject)() );
1857   selectionDone();
1858
1859   checkSubMeshConcurrency( aMeshVar, aSubMeshVar, /*askUser=*/true );
1860
1861   return true;
1862 }
1863
1864 //================================================================================
1865 /*!
1866  * \brief Gets current hypothesis or algorithms
1867   * \param theDim - dimension of hypothesis or algorithm
1868   * \param theHypType - Type of hypothesis (Algo, MainHyp, AddHyp)
1869   * \retval int - current hypothesis or algorithms
1870  *
1871  * Gets current hypothesis or algorithms
1872  */
1873 //================================================================================
1874 int SMESHGUI_MeshOp::currentHyp( const int theDim, const int theHypType ) const
1875 {
1876   return myDlg->tab( theDim )->currentHyp( theHypType ) - 1;
1877 }
1878
1879 //================================================================================
1880 /*!
1881  * \brief Returns true if hypotheses of given dim can be assigned
1882   * \param theDim - hypotheses dimension
1883   * \retval bool - result
1884  */
1885 //================================================================================
1886 bool SMESHGUI_MeshOp::isAccessibleDim( const int theDim ) const
1887 {
1888   return myDlg->isTabEnabled( theDim );
1889 }
1890
1891 //================================================================================
1892 /*!
1893  * \brief Sets current hypothesis or algorithms
1894   * \param theDim - dimension of hypothesis or algorithm
1895   * \param theHypType - Type of hypothesis (Algo, MainHyp, AddHyp)
1896   * \param theIndex - Index of hypothesis
1897  *
1898  * Gets current hypothesis or algorithms
1899  */
1900 //================================================================================
1901 void SMESHGUI_MeshOp::setCurrentHyp( const int theDim,
1902                                      const int theHypType,
1903                                      const int theIndex )
1904 {
1905   myIgnoreAlgoSelection = true;
1906   myDlg->tab( theDim )->setCurrentHyp( theHypType, theIndex + 1 );
1907   myIgnoreAlgoSelection = false;
1908 }
1909
1910 //================================================================================
1911 /*!
1912  * \brief Generates default and sets mesh/submesh name
1913  *
1914  * Generates and sets default mesh/submesh name(Mesh_1, Mesh_2, etc.)
1915  */
1916 //================================================================================
1917 void SMESHGUI_MeshOp::setDefaultName( const QString& thePrefix ) const
1918 {
1919   QString aResName;
1920
1921   _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
1922   int i = 1;
1923
1924   QString aPrefix = thePrefix;
1925   if ( aPrefix.isEmpty() )
1926     aPrefix = tr( myIsMesh ? "SMESH_OBJECT_MESH" : "SMESH_SUBMESH" ) + "_";
1927
1928   _PTR(SObject) anObj;
1929   do
1930   {
1931     aResName = aPrefix + QString::number( i++ );
1932     anObj = aStudy->FindObject( aResName.toLatin1().data() );
1933   }
1934   while ( anObj );
1935
1936   QLineEdit* aControl = ( QLineEdit* )myDlg->objectWg(
1937     SMESHGUI_MeshDlg::Obj, SMESHGUI_MeshDlg::Control );
1938   aControl->setText( aResName );
1939 }
1940
1941 //================================================================================
1942 /*!
1943  * \brief Gets algorithm or creates it if necessary
1944   * \param theDim - specifies dimension of returned hypotheses/algorifms
1945   * \retval SMESH::SMESH_Hypothesis_var - algorithm
1946  *
1947  * Gets algorithm or creates it if necessary
1948  */
1949 //================================================================================
1950 SMESH::SMESH_Hypothesis_var SMESHGUI_MeshOp::getAlgo( const int theDim )
1951 {
1952   SMESH::SMESH_Hypothesis_var anAlgoVar;
1953
1954   // get type of the selected algo
1955   int aHypIndex = currentHyp( theDim, Algo );
1956   THypDataList& dataList = myAvailableHypData[ theDim ][ Algo ];
1957   if ( aHypIndex < 0 || aHypIndex >= dataList.count())
1958     return anAlgoVar;
1959   QString aHypName = dataList[ aHypIndex ]->TypeName;
1960
1961   // get existing algoritms
1962   _PTR(SObject) pObj = SMESH::GetActiveStudyDocument()->FindComponent("SMESH");
1963   QStringList tmp;
1964   existingHyps( theDim, Algo, pObj, tmp, myExistingHyps[ theDim ][ Algo ]);
1965
1966   // look for an existing algo of such a type
1967   THypList& aHypVarList = myExistingHyps[ theDim ][ Algo ];
1968   THypList::iterator anIter = aHypVarList.begin();
1969   for ( ; anIter != aHypVarList.end(); anIter++)
1970   {
1971     SMESH::SMESH_Hypothesis_var aHypVar = (*anIter).first;
1972     if ( !aHypVar->_is_nil() && aHypName == SMESH::toQStr( aHypVar->GetName() ))
1973     {
1974       anAlgoVar = aHypVar;
1975       break;
1976     }
1977   }
1978
1979   if (anAlgoVar->_is_nil())
1980   {
1981     HypothesisData* aHypData = SMESH::GetHypothesisData( aHypName );
1982     if (aHypData)
1983     {
1984       QString aClientLibName = aHypData->ClientLibName;
1985       if ( aClientLibName.isEmpty() )
1986       {
1987         // Call hypothesis creation server method (without GUI)
1988         SMESH::SMESH_Hypothesis_var aHyp =
1989           SMESH::CreateHypothesis(aHypName, aHypName, true);
1990         aHyp.out();
1991       }
1992       else
1993       {
1994         // Get hypotheses creator client (GUI)
1995         SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator(aHypName);
1996
1997         // Create algorithm
1998         if (aCreator)
1999           aCreator->create( true, aHypName, myDlg, 0, QString::null );
2000         else {
2001           SMESH::SMESH_Hypothesis_var aHyp =
2002             SMESH::CreateHypothesis(aHypName, aHypName, true);
2003           aHyp.out();
2004         }
2005       }
2006       QStringList tmpList;
2007       _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
2008       existingHyps( theDim, Algo, aFather, tmpList, myExistingHyps[ theDim ][ Algo ] );
2009     }
2010
2011     THypList& aNewHypVarList = myExistingHyps[ theDim ][ Algo ];
2012     for ( anIter = aNewHypVarList.begin(); anIter != aNewHypVarList.end(); ++anIter )
2013     {
2014       SMESH::SMESH_Hypothesis_var aHypVar = (*anIter).first;
2015       if ( !aHypVar->_is_nil() && aHypName == SMESH::toQStr( aHypVar->GetName() ))
2016       {
2017         anAlgoVar = aHypVar;
2018         break;
2019       }
2020     }
2021   }
2022
2023   return anAlgoVar._retn();
2024 }
2025
2026 //================================================================================
2027 /*!
2028  * \brief Reads parameters of an edited mesh/sub-mesh and assigns them to the dialog
2029  *
2030  * Called when mesh is edited only.
2031  */
2032 //================================================================================
2033 void SMESHGUI_MeshOp::readMesh()
2034 {
2035   QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
2036   _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.toLatin1().data() );
2037   if ( !pObj )
2038     return;
2039
2040   if (myIsOnGeometry) {
2041     // Get name of mesh if current object is sub-mesh
2042     SMESH::SMESH_subMesh_var aSubMeshVar =
2043       SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() );
2044     if ( !aSubMeshVar->_is_nil() )
2045     {
2046       SMESH::SMESH_Mesh_var aMeshVar =  aSubMeshVar->GetFather();
2047       if ( !aMeshVar->_is_nil() )
2048       {
2049         _PTR(SObject) aMeshSO = SMESH::FindSObject( aMeshVar );
2050         QString aMeshName = name( aMeshSO );
2051         myDlg->setObjectText( SMESHGUI_MeshDlg::Mesh, aMeshName );
2052       }
2053       myHasConcurrentSubBefore = checkSubMeshConcurrency( aMeshVar, aSubMeshVar );
2054     }
2055
2056     // Get name of geometry object
2057     CORBA::String_var name = SMESH::GetGeomName( pObj );
2058     if ( name.in() )
2059       myDlg->setObjectText( SMESHGUI_MeshDlg::Geom, name.in() );
2060   }
2061
2062   // Get hypotheses and algorithms assigned to the mesh/sub-mesh
2063   QStringList anExisting;
2064   const int lastDim = ( myIsOnGeometry ) ? SMESH::DIM_0D : SMESH::DIM_3D;
2065   bool algoFound = false;
2066   for ( int dim = SMESH::DIM_3D; dim >= lastDim; --dim )
2067   {
2068     // get algorithm
2069     existingHyps( dim, Algo, pObj, anExisting, myObjHyps[ dim ][ Algo ] );
2070     // find algo index among available ones
2071     int aHypIndex = -1;
2072     if ( myObjHyps[ dim ][ Algo ].count() > 0 )
2073     {
2074       SMESH::SMESH_Hypothesis_var aVar = myObjHyps[ dim ][ Algo ].first().first;
2075       HypothesisData* algoData = SMESH::GetHypothesisData( aVar->GetName() );
2076       aHypIndex = myAvailableHypData[ dim ][ Algo ].indexOf ( algoData );
2077 //       if ( aHypIndex < 0 && algoData ) {
2078 //         // assigned algo is incompatible with other algorithms
2079 //         myAvailableHypData[ dim ][ Algo ].push_back( algoData );
2080 //         aHypIndex = myAvailableHypData[ dim ][ hypType ].count() - 1;
2081 //       }
2082       algoFound = ( aHypIndex > -1 );
2083     }
2084     setCurrentHyp( dim, Algo, aHypIndex );
2085     // set existing and available hypothesis according to the selected algo
2086     if ( aHypIndex > -1 || !algoFound )
2087       onAlgoSelected( aHypIndex, dim );
2088   }
2089
2090   // get hypotheses
2091   bool hypWithoutAlgo = false;
2092   for ( int dim = SMESH::DIM_3D; dim >= lastDim; --dim )
2093   {
2094     for ( int hypType = MainHyp; hypType <= AddHyp; hypType++ )
2095     {
2096       // get hypotheses
2097       existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] );
2098       // find index of requered hypothesis among existing ones for this dimension and type
2099       int aHypIndex = -1;
2100       if ( myObjHyps[ dim ][ hypType ].count() > 0 ) {
2101         aHypIndex = find( myObjHyps[ dim ][ hypType ].first().first,
2102                           myExistingHyps[ dim ][ hypType ] );
2103         if ( aHypIndex < 0 ) {
2104           // assigned hypothesis is incompatible with the algorithm
2105           if ( currentHyp( dim, Algo ) < 0 )
2106           { // none algo selected; it is edition for sure, of submesh maybe
2107             hypWithoutAlgo = true;
2108             myExistingHyps[ dim ][ hypType ].push_back( myObjHyps[ dim ][ hypType ].first() );
2109             aHypIndex = myExistingHyps[ dim ][ hypType ].count() - 1;
2110             myDlg->tab( dim )->setExistingHyps( hypType, anExisting );
2111           }
2112         }
2113       }
2114       setCurrentHyp( dim, hypType, aHypIndex );
2115     }
2116   }
2117   // make available other hyps of same type as one without algo
2118   if ( hypWithoutAlgo )
2119     onAlgoSelected( currentHyp( 0, Algo ), 0 );
2120 }
2121
2122 //================================================================================
2123 /*!
2124  * \brief Gets name of object
2125   * \param theSO - SObject
2126   * \retval QString - name of object
2127  *
2128  * Gets name of object
2129  */
2130 //================================================================================
2131 QString SMESHGUI_MeshOp::name( _PTR(SObject) theSO ) const
2132 {
2133   QString aResName;
2134   if ( theSO )
2135   {
2136     _PTR(GenericAttribute) anAttr;
2137     _PTR(AttributeName)    aNameAttr;
2138     if ( theSO->FindAttribute( anAttr, "AttributeName" ) )
2139     {
2140       aNameAttr = anAttr;
2141       aResName = aNameAttr->Value().c_str();
2142     }
2143   }
2144   return aResName;
2145 }
2146
2147 //================================================================================
2148 /*!
2149  * \brief Finds hypothesis in input list
2150   * \param theHyp - hypothesis to be found
2151   * \param theHypList - input list of hypotheses
2152   * \retval int - index of hypothesis or -1 if it is not found
2153  *
2154  * Finds position of hypothesis in input list
2155  */
2156 //================================================================================
2157 int SMESHGUI_MeshOp::find( const SMESH::SMESH_Hypothesis_var& theHyp,
2158                            const THypList& theHypList ) const
2159 {
2160   int aRes = -1;
2161   if ( !theHyp->_is_nil() )
2162   {
2163     int i = 0;
2164     THypList::const_iterator anIter = theHypList.begin();
2165     for ( ; anIter != theHypList.end(); ++ anIter)
2166     {
2167       if ( theHyp->_is_equivalent( (*anIter).first ) )
2168       {
2169         aRes = i;
2170         break;
2171       }
2172       i++;
2173     }
2174   }
2175   return aRes;
2176 }
2177
2178 //================================================================================
2179 /*!
2180  * \brief Edits mesh or sub-mesh
2181   * \param theMess - Output parameter intended for returning error message
2182   * \retval bool  - TRUE if mesh is edited succesfully, FALSE otherwise
2183  *
2184  * Assigns new name hypotheses and algoriths to the mesh or sub-mesh
2185  */
2186 //================================================================================
2187 bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess )
2188 {
2189   theMess = "";
2190
2191   SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen();
2192   if ( aSMESHGen->_is_nil() )
2193     return false;
2194
2195   QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
2196   _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.toLatin1().data() );
2197   if ( !pObj )
2198     return false;
2199
2200   SUIT_OverrideCursor aWaitCursor;
2201
2202   // Set new name
2203   QString aName = myDlg->objectText( SMESHGUI_MeshDlg::Obj );
2204   SMESH::SetName( pObj, aName );
2205   int aDim = ( myIsOnGeometry ) ? SMESH::DIM_0D : SMESH::DIM_3D;
2206
2207   // First, remove old algos in order to avoid messages on algorithm hiding
2208   for ( int dim = aDim; dim <= SMESH::DIM_3D; dim++ )
2209   {
2210     if ( isAccessibleDim( dim ) && myObjHyps[ dim ][ Algo ].count() > 0 )
2211     {
2212       SMESH::SMESH_Hypothesis_var anOldAlgo = myObjHyps[ dim ][ Algo ].first().first;
2213       SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( dim );
2214       if ( anAlgoVar->_is_nil() || // no new algo selected or
2215            strcmp(anOldAlgo->GetName(), anAlgoVar->GetName()) ) // algo change
2216       {
2217         // remove old algorithm
2218         SMESH::RemoveHypothesisOrAlgorithmOnMesh ( pObj, myObjHyps[ dim ][ Algo ].first().first );
2219         myObjHyps[ dim ][ Algo ].clear();
2220       }
2221     }
2222   }
2223
2224   SALOMEDS_SObject* aSObject = _CAST(SObject, pObj);
2225   CORBA::Object_var anObject = aSObject->GetObject();
2226   SMESH::SMESH_Mesh_var       aMeshVar = SMESH::SMESH_Mesh::_narrow( anObject );
2227   SMESH::SMESH_subMesh_var aSubMeshVar = SMESH::SMESH_subMesh::_narrow( anObject );
2228   bool isMesh = !aMeshVar->_is_nil();
2229   if ( !isMesh && !aSubMeshVar->_is_nil() )
2230     aMeshVar = aSubMeshVar->GetFather();
2231
2232   // Assign new algorithms and hypotheses
2233   for ( int dim = aDim; dim <= SMESH::DIM_3D; dim++ )
2234   {
2235     if ( !isAccessibleDim( dim )) continue;
2236
2237     // find or create algorithm
2238     SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( dim );
2239
2240     // assign new algorithm
2241     if ( !anAlgoVar->_is_nil() && // some algo selected and
2242          myObjHyps[ dim ][ Algo ].count() == 0 ) // no algo assigned
2243     {
2244       if ( isMesh )
2245         SMESH::AddHypothesisOnMesh( aMeshVar, anAlgoVar );
2246       else if ( !aSubMeshVar->_is_nil() )
2247         SMESH::AddHypothesisOnSubMesh( aSubMeshVar, anAlgoVar );
2248
2249       myObjHyps[ dim ][ Algo ].append( THypItem( anAlgoVar, aName) );
2250     }
2251
2252     // assign hypotheses
2253     for ( int hypType = MainHyp; hypType <= AddHyp; hypType++ )
2254     {
2255       int aNewHypIndex = currentHyp( dim, hypType );
2256       int anOldHypIndex = -1;
2257
2258       // remove old hypotheses
2259       if ( myObjHyps[ dim ][ hypType ].count() > 0 )
2260       {
2261         anOldHypIndex = find( myObjHyps[ dim ][ hypType ].first().first,
2262                               myExistingHyps[ dim ][ hypType ] );
2263         if ( aNewHypIndex != anOldHypIndex || // different hyps
2264              anOldHypIndex == -1 )            // hyps of different algos
2265         {
2266           SMESH::RemoveHypothesisOrAlgorithmOnMesh
2267             ( pObj, myObjHyps[ dim ][ hypType ].first().first );
2268           myObjHyps[ dim ][ hypType ].clear();
2269         }
2270       }
2271
2272       // assign new hypotheses
2273       if ( aNewHypIndex != anOldHypIndex && aNewHypIndex > -1 )
2274       {
2275         if ( isMesh )
2276           SMESH::AddHypothesisOnMesh
2277             (aMeshVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ].first );
2278         else if ( !aSubMeshVar->_is_nil() )
2279           SMESH::AddHypothesisOnSubMesh
2280             ( aSubMeshVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ].first );
2281       }
2282       // reread all hypotheses of mesh if necessary
2283       QStringList anExisting;
2284       existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] );
2285     }
2286   }
2287
2288   myHasConcurrentSubBefore =
2289     checkSubMeshConcurrency( aMeshVar, aSubMeshVar, /*askUser=*/!myHasConcurrentSubBefore );
2290
2291   return true;
2292 }
2293
2294 //================================================================================
2295 /*!
2296  * \brief Checks if a concurrent sub-meshes appear as result of sub-mesh
2297  *        creation/edition and, if (askUser) , proposes the uses to set up a desired
2298  *        order of sub-mesh computation.
2299  *        Returns \c true if a sub-mesh concurrency detected.
2300  */
2301 //================================================================================
2302
2303 bool SMESHGUI_MeshOp::checkSubMeshConcurrency(SMESH::SMESH_Mesh_ptr    mesh,
2304                                               SMESH::SMESH_subMesh_ptr submesh,
2305                                               bool                     askUser)
2306 {
2307   if ( CORBA::is_nil( mesh ) || CORBA::is_nil( submesh ))
2308     return false;
2309
2310   bool isNewConcurrent = mesh->IsUnorderedSubMesh( submesh->GetId() );
2311   if ( isNewConcurrent && askUser )
2312   {
2313     int butID = SUIT_MessageBox::warning( myDlg->parentWidget(), tr( "SMESH_WARNING" ),
2314                                           tr("CONCURRENT_SUBMESH_APPEARS"),
2315                                           tr("SMESH_BUT_YES"), tr("SMESH_BUT_NO"));
2316     if ( butID == 0 )
2317     {
2318       _PTR(SObject) meshSO = SMESH::FindSObject( mesh );
2319       LightApp_SelectionMgr* aSelectionMgr = selectionMgr();
2320       if ( meshSO && aSelectionMgr )
2321       {
2322         myDlg->setEnabled( false ); // disactivate selection
2323         selectionMgr()->clearFilters();
2324         selectObject( meshSO );
2325         SMESHGUI::GetSMESHGUI()->OnGUIEvent( 713 ); // MESH_ORDER
2326         qApp->processEvents();
2327
2328         myDlg->setEnabled( true );
2329         int obj = myDlg->getActiveObject();
2330         onActivateObject( obj ); // restore filter
2331         if ( !myToCreate )
2332         {
2333           selectObject( SMESH::FindSObject( submesh ));
2334           selectionDone();
2335         }
2336       }
2337     }
2338   }
2339
2340   return isNewConcurrent;
2341 }
2342
2343 //================================================================================
2344 /*!
2345  * \brief Verifies whether given operator is valid for this one
2346  * \param theOtherOp - other operation
2347  * \return Returns TRUE if the given operator is valid for this one, FALSE otherwise
2348  *
2349  * method redefined from base class verifies whether given operator is valid for
2350  * this one (i.e. can be started "above" this operator). In current implementation method
2351  * retuns false if theOtherOp operation is not intended for deleting objects or mesh
2352  * elements.
2353  */
2354 //================================================================================
2355 bool SMESHGUI_MeshOp::isValid( SUIT_Operation* theOp ) const
2356 {
2357   return SMESHGUI_Operation::isValid( theOp ) && !theOp->inherits( "SMESHGUI_MeshOp" );
2358 }
2359
2360 //================================================================================
2361 /*!
2362  * \brief SLOT. Is called when the user selects a way of geometry selection
2363  * \param theByMesh - true if the user wants to find geometry by mesh element
2364  */
2365 //================================================================================
2366 void SMESHGUI_MeshOp::onGeomSelectionByMesh( bool theByMesh )
2367 {
2368   if ( theByMesh ) {
2369     if ( !myShapeByMeshOp ) {
2370       myShapeByMeshOp = new SMESHGUI_ShapeByMeshOp();
2371       connect(myShapeByMeshOp, SIGNAL(committed(SUIT_Operation*)),
2372               SLOT(onPublishShapeByMeshDlg(SUIT_Operation*)));
2373       connect(myShapeByMeshOp, SIGNAL(aborted(SUIT_Operation*)),
2374               SLOT(onCloseShapeByMeshDlg(SUIT_Operation*)));
2375     }
2376     // set mesh object to SMESHGUI_ShapeByMeshOp and start it
2377     QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
2378     if ( _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.toLatin1().data() )) {
2379       SMESH::SMESH_Mesh_var aMeshVar =
2380         SMESH::SMESH_Mesh::_narrow( _CAST( SObject,pMesh )->GetObject() );
2381       if ( !aMeshVar->_is_nil() ) {
2382         myDlg->hide(); // stop processing selection
2383         myShapeByMeshOp->setModule( getSMESHGUI() );
2384         myShapeByMeshOp->setStudy( 0 ); // it's really necessary
2385         myShapeByMeshOp->SetMesh( aMeshVar );
2386         myShapeByMeshOp->start();
2387       }
2388     }
2389   }
2390 }
2391
2392 //================================================================================
2393 /*!
2394  * \brief SLOT. Is called when Ok is pressed in SMESHGUI_ShapeByMeshDlg
2395  */
2396 //================================================================================
2397 void SMESHGUI_MeshOp::onPublishShapeByMeshDlg(SUIT_Operation* op)
2398 {
2399   if ( myShapeByMeshOp == op ) {
2400     SMESHGUI::GetSMESHGUI()->getApp()->updateObjectBrowser(); //MZN: 24.11.2006  IPAL13980 - Object Browser update added
2401     myDlg->show();
2402     // Select a found geometry object
2403     GEOM::GEOM_Object_var aGeomVar = myShapeByMeshOp->GetShape();
2404     if ( !aGeomVar->_is_nil() )
2405     {
2406       QString ID = SMESH::toQStr( aGeomVar->GetStudyEntry() );
2407       if ( _PTR(SObject) aGeomSO = studyDS()->FindObjectID( ID.toLatin1().data() )) {
2408         selectObject( aGeomSO );
2409         selectionDone();
2410       }
2411     }
2412   }
2413 }
2414
2415 //================================================================================
2416 /*!
2417  * \brief SLOT. Is called when Close is pressed in SMESHGUI_ShapeByMeshDlg
2418  */
2419 //================================================================================
2420 void SMESHGUI_MeshOp::onCloseShapeByMeshDlg(SUIT_Operation* op)
2421 {
2422   if ( myShapeByMeshOp == op && myDlg ) {
2423     myDlg->show();
2424   }
2425 }
2426
2427 //================================================================================
2428 /*!
2429  * \brief Selects a SObject
2430  * \param theSObj - the SObject to select
2431  */
2432 //================================================================================
2433 void SMESHGUI_MeshOp::selectObject( _PTR(SObject) theSObj ) const
2434 {
2435   if ( LightApp_SelectionMgr* sm = selectionMgr() ) {
2436     SALOME_ListIO anIOList;
2437     if ( theSObj ) {
2438       Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject
2439         ( theSObj->GetID().c_str(), "SMESH", theSObj->GetName().c_str() );
2440       anIOList.Append( anIO );
2441     }
2442     sm->setSelectedObjects( anIOList, false );
2443   }
2444 }
2445 //================================================================================
2446 /*!
2447  * \brief Create available list types of mesh
2448   * \param theTypeMesh - Output list of available types of mesh
2449  */
2450 //================================================================================
2451 void SMESHGUI_MeshOp::createMeshTypeList( QStringList& theTypeMesh)
2452 {
2453   theTypeMesh.clear();
2454   theTypeMesh.append( tr( "MT_ANY" ) );
2455   if ( myMaxShapeDim >= 2 || myMaxShapeDim == -1 )
2456   {
2457     theTypeMesh.append( tr( "MT_TRIANGULAR" ) );
2458     theTypeMesh.append( tr( "MT_QUADRILATERAL" ) );
2459   }
2460   if ( myMaxShapeDim == 3 || myMaxShapeDim == -1 )
2461   {
2462     theTypeMesh.append( tr( "MT_TETRAHEDRAL" ) );
2463     theTypeMesh.append( tr( "MT_HEXAHEDRAL" ) );
2464   }
2465
2466 }
2467 //================================================================================
2468 /*!
2469  * \brief Set available types of mesh
2470   * \param theTypeMesh - List of available types of mesh
2471  */
2472 //================================================================================
2473 void SMESHGUI_MeshOp::setAvailableMeshType( const QStringList& theTypeMesh )
2474 {
2475   myDlg->setAvailableMeshType( theTypeMesh );
2476 }
2477
2478 //================================================================================
2479 /*!
2480  * \brief SLOT. Is called when the user select type of mesh
2481   * \param theTabIndex - Index of current active tab
2482   * \param theIndex - Index of current type of mesh
2483  */
2484 //================================================================================
2485 void SMESHGUI_MeshOp::onAlgoSetByMeshType( const int theTabIndex, const int theIndex)
2486 {
2487   setFilteredAlgoData( theTabIndex, theIndex);
2488 }
2489
2490 //================================================================================
2491 /*!
2492  * \brief Set a filtered list of available algorithms by mesh type
2493   * \param theTabIndex - Index of current active tab
2494   * \param theIndex - Index of current type of mesh
2495  */
2496 //================================================================================
2497 void SMESHGUI_MeshOp::setFilteredAlgoData( const int theTabIndex, const int theIndex)
2498 {
2499   int aDim;
2500   THypDataList anAvailableAlgsData;
2501   QStringList anAvailableAlgs;
2502   QString anCompareType = "";
2503   bool isAvailableChoiceAlgo = false;
2504   int anCurrentAvailableAlgo = 0;
2505   bool isNone = true;
2506   switch ( theIndex ) {
2507   case MT_ANY:
2508     anCompareType = "ANY";
2509     aDim = SMESH::DIM_3D;
2510     break;
2511   case MT_TRIANGULAR:
2512     aDim = SMESH::DIM_2D;
2513     anCompareType = "TRIA";
2514     break;
2515   case MT_QUADRILATERAL:
2516     aDim = SMESH::DIM_2D;
2517     anCompareType = "QUAD";
2518     break;
2519   case MT_TETRAHEDRAL:
2520     aDim = SMESH::DIM_3D;
2521     anCompareType = "TETRA";
2522     break;
2523   case MT_HEXAHEDRAL:
2524     aDim = SMESH::DIM_3D;
2525     anCompareType = "HEXA";
2526     break;
2527   default:;
2528   }
2529
2530   bool toCheckIsApplicableToAll = !myIsMesh;
2531   GEOM::GEOM_Object_var aGeomVar;
2532   QString anEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
2533   if ( _PTR(SObject) so = studyDS()->FindObjectID( anEntry.toLatin1().data() ))
2534   {
2535     CORBA::Object_var obj = _CAST( SObject,so )->GetObject();
2536     aGeomVar = GEOM::GEOM_Object::_narrow( obj );
2537     if ( !aGeomVar->_is_nil() && toCheckIsApplicableToAll )
2538       toCheckIsApplicableToAll = ( aGeomVar->GetType() == GEOM_GROUP );
2539   }
2540
2541   if ( anCompareType == "ANY" )
2542   {
2543     for ( int dim = SMESH::DIM_3D; dim >= SMESH::DIM_2D; dim-- )
2544     {
2545       isNone = currentHyp( dim, Algo ) < 0;
2546       isAvailableChoiceAlgo = false;
2547       // retrieves a list of available algorithms from resources
2548       availableHyps( dim, Algo, anAvailableAlgs, anAvailableAlgsData );
2549       //return current algo in current tab and set new algorithm list
2550       HypothesisData* algoCur;
2551       if ( !isNone && !myAvailableHypData[dim][Algo].empty() ) {
2552         algoCur = myAvailableHypData[dim][Algo].at( currentHyp( dim, Algo ) );
2553       }
2554       myAvailableHypData[dim][Algo].clear();
2555       anAvailableAlgs.clear();
2556       if ( dim != SMESH::DIM_2D || currentHyp( SMESH::DIM_3D, Algo ) < 0 ||
2557            myAvailableHypData[SMESH::DIM_3D][Algo].empty() ||
2558            !myAvailableHypData[SMESH::DIM_3D][Algo].at( currentHyp( SMESH::DIM_3D, Algo ) )->InputTypes.isEmpty() )
2559       {
2560         for (int i = 0 ; i < anAvailableAlgsData.count(); i++)
2561         {
2562           HypothesisData* curAlgo = anAvailableAlgsData.at(i);
2563           if ( aGeomVar->_is_nil() ||
2564               SMESH::IsApplicable( curAlgo->TypeName, aGeomVar, toCheckIsApplicableToAll ))
2565           {
2566             anAvailableAlgs.append( curAlgo->Label );
2567             myAvailableHypData[dim][Algo].append( curAlgo );
2568           }
2569         }
2570         if ( !isNone && algoCur ) {
2571           for (int i = 0 ; i < myAvailableHypData[dim][Algo].count(); i++)
2572           {
2573             HypothesisData* algoAny = myAvailableHypData[dim][Algo].at(i);
2574             if ( algoAny->Label == algoCur->Label ){
2575               isAvailableChoiceAlgo = true;
2576               anCurrentAvailableAlgo = i;
2577               break;
2578             }
2579           }
2580         }
2581         else if ( !isNone ) {
2582           isAvailableChoiceAlgo = true;
2583           anCurrentAvailableAlgo = currentHyp( dim, Algo );
2584         }
2585       }
2586       myDlg->tab( dim )->setAvailableHyps( Algo, anAvailableAlgs );
2587       if ( isAvailableChoiceAlgo )
2588         setCurrentHyp( dim, Algo, anCurrentAvailableAlgo );
2589     }
2590     if ( !myIsOnGeometry )
2591       for ( int i = SMESH::DIM_0D; i <= SMESH::DIM_3D; i++ ) {
2592         if ( i < SMESH::DIM_3D ) myDlg->disableTab( i );
2593         else                     myDlg->enableTab( i );
2594       }
2595     else
2596       for ( int i = SMESH::DIM_0D; i <= SMESH::DIM_3D; i++ ) {
2597         if ( i > myMaxShapeDim ) myDlg->disableTab( i );
2598         else                     myDlg->enableTab( i );
2599       }
2600     myDlg->setCurrentTab( theTabIndex );
2601   }
2602   else
2603   {
2604     QString anCurrentAlgo;
2605     bool isReqDisBound = true;
2606     QString anCurrentCompareType = anCompareType;
2607     isNone = currentHyp( aDim, Algo ) < 0;
2608     if ( !isNone && !myAvailableHypData[aDim][Algo].empty() &&
2609         myAvailableHypData[aDim][Algo].count() != anAvailableAlgsData.count() )
2610       isReqDisBound = myAvailableHypData[aDim][Algo].at( currentHyp( aDim, Algo ) )->InputTypes.isEmpty();
2611     else if ( !isNone )
2612       isReqDisBound = anAvailableAlgsData.at( currentHyp( aDim, Algo ) )->InputTypes.isEmpty();
2613     for ( int dim = aDim; dim >= SMESH::DIM_2D; dim-- )
2614     {
2615       bool isNoneAlg = currentHyp( dim, Algo ) < 0;
2616       isAvailableChoiceAlgo = false;
2617       // retrieves a list of available algorithms from resources
2618       availableHyps( dim, Algo, anAvailableAlgs, anAvailableAlgsData );
2619       // finding algorithm which is selected
2620       if ( !isNoneAlg && !myAvailableHypData[dim][Algo].empty() &&
2621           myAvailableHypData[dim][Algo].count() != anAvailableAlgsData.count() )
2622         anCurrentAlgo = myAvailableHypData[dim][Algo].at( currentHyp( dim, Algo ) )->Label;
2623       else if ( !isNoneAlg )
2624         anCurrentAlgo = anAvailableAlgsData.at( currentHyp( dim, Algo ) )->Label;
2625       anAvailableAlgs.clear();
2626       myAvailableHypData[dim][Algo].clear();
2627       myFilteredAlgoData[dim].clear();
2628       // finding and adding algorithm depending on the type mesh
2629       for ( int i = 0 ; i < anAvailableAlgsData.count(); i++ )
2630       {
2631         HypothesisData* algoIn = anAvailableAlgsData.at( i );
2632         bool isAvailableAlgo = ( algoIn->OutputTypes.count() == 0 );
2633         QStringList::const_iterator inElemType = algoIn->OutputTypes.begin();
2634         for ( ; inElemType != algoIn->OutputTypes.end(); inElemType++ )
2635         {
2636           if ( *inElemType == anCurrentCompareType ) {
2637             isAvailableAlgo = true;
2638             break;
2639           }
2640         }
2641         if ( isAvailableAlgo || algoIn->OutputTypes.count()==0 ) {
2642           if ( aGeomVar->_is_nil() || myMaxShapeDim != dim ||
2643                SMESH::IsApplicable( algoIn->TypeName, aGeomVar, toCheckIsApplicableToAll ))
2644           {
2645             anAvailableAlgs.append( algoIn->Label );
2646             myAvailableHypData[dim][Algo].append( algoIn );
2647             myFilteredAlgoData[dim].append( algoIn );
2648           }
2649         }
2650         //algorithm will be active, if the chosen algorithm available in the current mesh type
2651         if ( !isNoneAlg &&  isAvailableAlgo && algoIn->Label == anCurrentAlgo ) {
2652           isAvailableChoiceAlgo = true;
2653           anCurrentAvailableAlgo = anAvailableAlgs.count() - 1 ;
2654         }
2655       }
2656       //set new algorithm list and select the current algorithm
2657       myDlg->tab( dim )->setAvailableHyps( Algo, anAvailableAlgs );
2658       anCurrentCompareType = ( anCompareType == "HEXA" ) ? "QUAD" : "TRIA";
2659       if ( isAvailableChoiceAlgo )
2660         setCurrentHyp( dim, Algo, anCurrentAvailableAlgo );
2661       else
2662         setCurrentHyp( dim, Algo, -1 );
2663     }
2664
2665     if ( isNone || isReqDisBound ) {
2666       for ( int i = SMESH::DIM_0D; i <= myMaxShapeDim; i++ ) {
2667         if ( aDim != i ) {
2668           myDlg->disableTab( i );
2669           setCurrentHyp(i, Algo, -1);
2670         }
2671       }
2672     }
2673     else if ( !isNone ) {
2674       if ( aDim == SMESH::DIM_2D){
2675         myDlg->disableTab( SMESH::DIM_3D );
2676         setCurrentHyp( SMESH::DIM_3D, Algo, -1);
2677       }
2678       for ( int i = myMaxShapeDim; i > SMESH::DIM_0D; i-- )
2679       {
2680         isReqDisBound = ( currentHyp( i, Algo ) < 0 ) ? true :
2681             myAvailableHypData[i][Algo].at( currentHyp( i, Algo ) )->InputTypes.isEmpty();
2682         if ( isReqDisBound ) {
2683           for (int j = i - 1; j >= SMESH::DIM_0D; j--){
2684             myDlg->disableTab( j );
2685             setCurrentHyp( j , Algo, -1 );
2686           }
2687           break;
2688         }
2689       }
2690     }
2691     myDlg->enableTab( aDim );
2692     myDlg->setCurrentTab( aDim );
2693   }
2694   QStringList aHypothesesSetsList = SMESH::GetHypothesesSets( aDim );
2695   QStringList aFilteredHypothesesSetsList;
2696   aFilteredHypothesesSetsList.clear();
2697   QStringList::const_iterator inHypoSetName = aHypothesesSetsList.begin();
2698   for ( ; inHypoSetName != aHypothesesSetsList.end(); ++inHypoSetName )
2699   {
2700     HypothesesSet* currentHypoSet = SMESH::GetHypothesesSet( *inHypoSetName );
2701     bool isAvailable = false;
2702     currentHypoSet->init( true );
2703     while ( currentHypoSet->next(), currentHypoSet->more() )
2704     {
2705       isAvailable = false;
2706       if ( HypothesisData* algoDataIn = SMESH::GetHypothesisData( currentHypoSet->current() ))
2707       {
2708         for (int i = SMESH::DIM_0D; i <= myMaxShapeDim; i++)
2709         {
2710           if ( myAvailableHypData[i][Algo].count() == 0 ) {
2711             availableHyps( i, Algo, anAvailableAlgs, anAvailableAlgsData );
2712             for ( int j = 0 ; j < anAvailableAlgsData.count(); j++ )
2713             {
2714               HypothesisData* aCurAlgo = anAvailableAlgsData.at( j );
2715               if ( aCurAlgo->Label == algoDataIn->Label ){
2716                 isAvailable = true;
2717                 break;
2718               }
2719             }
2720           }
2721           else {
2722             for (int j = 0; j < myAvailableHypData[i][Algo].count(); ++j) {
2723               HypothesisData* aCurAlgo = hypData( i, Algo, j );
2724               if ( aCurAlgo->Label == algoDataIn->Label ){
2725                 isAvailable = true;
2726                 break;
2727               }
2728             }
2729           }
2730           if ( isAvailable ) break;
2731         }
2732         if ( !isAvailable ) break;
2733       }
2734     }
2735     if ( isAvailable )
2736       aFilteredHypothesesSetsList.append( *inHypoSetName );
2737   }
2738   myDlg->setHypoSets( aFilteredHypothesesSetsList );
2739 }