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