Salome HOME
PAL10513. Desable tabs according to shape dimention at edition as well
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MeshOp.cxx
1 /**
2 *  SMESH SMESHGUI
3 *
4 *  Copyright (C) 2005  CEA/DEN, EDF R&D
5 *
6 *
7 *
8 *  File   : SMESHGUI_MeshOp.h
9 *  Author : Sergey LITONIN
10 *  Module : SMESHGUI
11 */
12
13 #include "SMESHGUI_MeshOp.h"
14 #include "SMESHGUI_MeshDlg.h"
15 #include "SMESH_TypeFilter.hxx"
16 #include "SMESHGUI.h"
17
18 #include "SMESHGUI_HypothesesUtils.h"
19 #include "SMESHGUI_Hypotheses.h"
20 #include "SMESHGUI_Utils.h"
21 #include "SMESHGUI_GEOMGenUtils.h"
22
23 #include "SMESH_TypeFilter.hxx"
24 #include "SMESH_NumberFilter.hxx"
25
26 #include "GEOM_SelectionFilter.h"
27
28 #include "SalomeApp_Tools.h"
29 #include "SALOMEDSClient_Study.hxx"
30 #include "SALOMEDSClient_AttributeIOR.hxx"
31 #include "SALOMEDSClient_AttributeName.hxx"
32 #include "SALOMEDS_SComponent.hxx"
33 #include "SALOMEDS_SObject.hxx"
34
35
36 #include "LightApp_SelectionMgr.h"
37 #include "LightApp_UpdateFlags.h"
38 #include "SUIT_MessageBox.h"
39 #include "SUIT_Desktop.h"
40 #include "SUIT_OverrideCursor.h"
41
42 #include "GEOMBase.h"
43
44 #include "utilities.h"
45
46 #include <qstringlist.h>
47 #include <qlineedit.h>
48
49 #include <TopoDS_Shape.hxx>
50 #include <TopExp_Explorer.hxx>
51
52 //================================================================================
53 /*!
54  * \brief Constructor
55   * \param theToCreate - if this parameter is true then operation is used for creation,
56   * for editing otherwise
57  *
58  * Initialize operation
59 */
60 //================================================================================
61 SMESHGUI_MeshOp::SMESHGUI_MeshOp( const bool theToCreate, const bool theIsMesh )
62 : SMESHGUI_SelectionOp(),
63   myToCreate( theToCreate ),
64   myIsMesh( theIsMesh ),
65   myDlg( 0 )
66 {
67 }
68
69 //================================================================================
70 /*!
71  * \brief Destructor
72 */
73 //================================================================================
74 SMESHGUI_MeshOp::~SMESHGUI_MeshOp()
75 {
76   if( myDlg )
77     delete myDlg;
78 }
79
80 //================================================================================
81 /*!
82  * \brief Gets dialog of this operation
83   * \retval LightApp_Dialog* - pointer to dialog of this operation
84 */
85 //================================================================================
86 LightApp_Dialog* SMESHGUI_MeshOp::dlg() const
87 {
88   return myDlg;
89 }
90
91 //================================================================================
92 /*!
93  * \brief Creates or edits mesh
94   * \retval bool - TRUE if operation is performed successfully, FALSE otherwise
95  *
96  * Virtual slot redefined from the base class called when "Apply" button is clicked
97  * creates or edits mesh
98  */
99 //================================================================================
100 bool SMESHGUI_MeshOp::onApply()
101 {
102   if( isStudyLocked() )
103     return false;
104
105   QString aMess;
106   if ( !isValid( aMess ) )
107   {
108     if ( aMess != "" )
109       SUIT_MessageBox::warn1( myDlg,
110         tr( "SMESH_WRN_WARNING" ), aMess, tr( "SMESH_BUT_OK" ) );
111     return false;
112   }
113
114   bool aResult = false;
115   aMess = "";
116   try
117   {
118     if ( myToCreate && myIsMesh )
119       aResult = createMesh( aMess );
120     if ( myToCreate && !myIsMesh )
121       aResult = createSubMesh( aMess );
122     else if ( !myToCreate )
123       aResult = editMeshOrSubMesh( aMess );
124     if ( aResult )
125       update( UF_ObjBrowser | UF_Model );
126   }
127   catch ( const SALOME::SALOME_Exception& S_ex )
128   {
129     SalomeApp_Tools::QtCatchCorbaException( S_ex );
130     aResult = false;
131   }
132   catch ( ... )
133   {
134     aResult = false;
135   }
136
137   if ( aResult )
138   {
139     if ( myToCreate )
140       setDefaultName();
141   }
142   else
143   {
144     if ( aMess == "" )
145       aMess = tr( "SMESH_OPERATION_FAILED" );
146     SUIT_MessageBox::warn1( myDlg,
147       tr( "SMESH_ERROR" ), aMess, tr( "SMESH_BUT_OK" ) );
148   }
149
150   return aResult;
151 }
152
153 //================================================================================
154 /*!
155  * \brief Creates dialog if necessary and shows it
156  *
157  * Virtual method redefined from base class called when operation is started creates
158  * dialog if necessary and shows it, activates selection
159  */
160 //================================================================================
161 void SMESHGUI_MeshOp::startOperation()
162 {
163   if( !myDlg )
164   {
165     myDlg = new SMESHGUI_MeshDlg( myToCreate, myIsMesh );
166     for ( int i = SMESH::DIM_1D; i <= SMESH::DIM_3D; i++ )
167     {
168       connect( myDlg->tab( i ), SIGNAL( createHyp( const int, const int ) ),
169               this, SLOT( onCreateHyp( const int, const int) ) );
170       connect( myDlg->tab( i ), SIGNAL( editHyp( const int, const int ) ),
171               this, SLOT( onEditHyp( const int, const int) ) );
172     }
173     connect( myDlg, SIGNAL( hypoSet( const QString& )), SLOT( onHypoSet( const QString& )));
174   }
175   SMESHGUI_SelectionOp::startOperation();
176
177   // iterate through dimensions and get available and existing algoritms and hypotheses,
178   // set them to the dialog
179   int i, j;
180   _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
181   for ( i = SMESH::DIM_1D; i <= SMESH::DIM_3D; i++ )
182   {
183     SMESHGUI_MeshTab* aTab = myDlg->tab( i );
184     QStringList anAvailable, anExisting;
185     for ( j = Algo; j <= AddHyp; j++ )
186     {
187       availableHyps( i, j, anAvailable );
188       existingHyps( i, j, aFather, anExisting, myExistingHyps[ i ][ j ] );
189
190       aTab->setAvailableHyps( j, anAvailable );
191       aTab->setExistingHyps( j, anExisting );
192     }
193   }
194   if ( myToCreate )
195   {
196     setDefaultName();
197     myDlg->activateObject( myIsMesh ? SMESHGUI_MeshDlg::Geom : SMESHGUI_MeshDlg::Mesh );
198   }
199   else
200     myDlg->activateObject( SMESHGUI_MeshDlg::Obj );
201
202   myDlg->setHypoSets( SMESH::GetHypothesesSets() );
203
204   selectionDone();
205
206   myDlg->setCurrentTab( SMESH::DIM_1D );
207   myDlg->show();
208 }
209
210 //================================================================================
211 /*!
212  * \brief Creates selection filter
213   * \param theId - identifier of current selection widget
214   * \retval SUIT_SelectionFilter* - pointer to the created filter or null
215  *
216  * Creates selection filter in accordance with identifier of current selection widget
217  */
218 //================================================================================
219 SUIT_SelectionFilter* SMESHGUI_MeshOp::createFilter( const int theId ) const
220 {
221   if ( theId == SMESHGUI_MeshDlg::Geom )
222   {
223 //     TColStd_MapOfInteger allTypesMap;
224 //     for ( int i = 0; i < 10; i++ )
225 //       allTypesMap.Add( i );
226 //     return new SMESH_NumberFilter( "GEOM", TopAbs_SHAPE, 0, allTypesMap );
227     return new GEOM_SelectionFilter( (SalomeApp_Study*)study(), true );
228   }
229   else if ( theId == SMESHGUI_MeshDlg::Obj && !myToCreate )
230     return new SMESH_TypeFilter( MESHorSUBMESH );
231   else if ( theId == SMESHGUI_MeshDlg::Mesh )
232     return new SMESH_TypeFilter( MESH );
233   else
234     return 0;
235 }
236
237 //================================================================================
238 /*!
239  * \brief Updates dialog's look and feel
240  *
241  * Virtual method redefined from the base class updates dialog's look and feel
242  */
243 //================================================================================
244 void SMESHGUI_MeshOp::selectionDone()
245 {
246   SMESHGUI_SelectionOp::selectionDone();
247
248   if ( !myToCreate )
249   {
250     try
251     {
252       QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
253       _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.latin1() );
254       if ( pObj != 0 )
255       {
256         SMESH::SMESH_subMesh_var aVar =
257           SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() );
258         myDlg->setObjectShown( SMESHGUI_MeshDlg::Mesh, !aVar->_is_nil() );
259         myDlg->objectWg( SMESHGUI_MeshDlg::Mesh, SMESHGUI_MeshDlg::Btn )->hide();
260         myDlg->updateGeometry();
261         myDlg->adjustSize();
262         readMesh();
263       }
264       else
265         myDlg->reset();
266     }
267     catch ( const SALOME::SALOME_Exception& S_ex )
268     {
269       SalomeApp_Tools::QtCatchCorbaException( S_ex );
270     }
271     catch ( ... )
272     {
273     }
274   }
275
276   // Enable tabs according to shape dimension
277
278   int shapeDim = 3;
279   try
280   {
281     GEOM::GEOM_Object_var aGeomVar;
282     QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
283     _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
284     if ( pGeom ) {
285       aGeomVar = GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
286     }
287     else {
288       QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
289       _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.latin1() );
290       aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj );
291     }
292     if ( !aGeomVar->_is_nil() ) {
293       shapeDim = 0;
294       switch ( aGeomVar->GetShapeType() ) {
295       case GEOM::SOLID:
296       case GEOM::SHELL:  shapeDim = 3; break;
297       case GEOM::FACE:   shapeDim = 2; break;
298       case GEOM::WIRE:   
299       case GEOM::EDGE:   shapeDim = 1; break;
300       case GEOM::VERTEX: shapeDim = 0; break;
301       default:
302         TopoDS_Shape aShape;
303         if ( GEOMBase::GetShape(aGeomVar, aShape)) {
304           TopExp_Explorer exp( aShape, TopAbs_SHELL );
305           if ( exp.More() )
306             shapeDim = 3;
307           else if ( exp.Init( aShape, TopAbs_FACE ), exp.More() )
308             shapeDim = 2;
309           else if ( exp.Init( aShape, TopAbs_EDGE ), exp.More() )
310             shapeDim = 1;
311           else
312             shapeDim = 0;
313         }
314       }
315     }
316   }
317   catch ( const SALOME::SALOME_Exception& S_ex )
318   {
319     SalomeApp_Tools::QtCatchCorbaException( S_ex );
320   }
321   catch ( ... )
322   {
323   }
324   myDlg->setMaxHypoDim( shapeDim );
325 }
326
327 //================================================================================
328 /*!
329  * \brief Verifies validity of input data
330   * \param theMess - Output parameter intended for returning error message
331   * \retval bool  - TRUE if input data is valid, false otherwise
332  *
333  * Verifies validity of input data. This method is called when "Apply" or "OK" button
334  * is pressed before mesh creation or editing.
335  */
336 //================================================================================
337 bool SMESHGUI_MeshOp::isValid( QString& theMess ) const
338 {
339   // Selected object to be  edited
340   if ( !myToCreate && myDlg->selectedObject( SMESHGUI_MeshDlg::Obj ) == "" )
341   {
342     theMess = tr( "THERE_IS_NO_OBJECT_FOR_EDITING" );
343     return false;
344   }
345
346   // Name
347   QString aMeshName = myDlg->objectText( SMESHGUI_MeshDlg::Obj );
348   aMeshName = aMeshName.stripWhiteSpace();
349   if ( aMeshName == "" )
350   {
351     theMess = myIsMesh ? tr( "NAME_OF_MESH_IS_EMPTY" ) : tr( "NAME_OF_SUBMESH_IS_EMPTY" );
352     return false;
353   }
354
355   // Geom
356   if ( myToCreate )
357   {
358     QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
359     if ( aGeomEntry == "" )
360     {
361       theMess = tr( "GEOMETRY_OBJECT_IS_NOT_DEFINED" );
362       return false;
363     }
364     _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
365     if ( !pGeom || GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() )->_is_nil() )
366     {
367       theMess = tr( "GEOMETRY_OBJECT_IS_NULL" );
368       return false;
369     }
370
371     // Mesh
372     if ( !myIsMesh ) // i.e sub-mesh creation,
373     {
374       QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
375       if ( aMeshEntry == "" )
376       {
377         theMess = tr( "MESH_IS_NOT_DEFINED" );
378         return false;
379       }
380       _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.latin1() );
381       if ( !pMesh || SMESH::SMESH_Mesh::_narrow( _CAST( SObject,pMesh )->GetObject() )->_is_nil() )
382       {
383         theMess = tr( "MESH_IS_NULL" );
384         return false;
385       }
386     }
387   }
388   return true;
389 }
390
391 //================================================================================
392 /*!
393  * \brief Gets available hypotheses or algorithms
394   * \param theDim - specifies dimension of returned hypotheses/algorifms
395   * \param theHypType - specifies whether algorims or hypotheses or additional ones
396   * are retrieved (possible values are in HypType enumeration)
397   * \param theHyps - Output list of hypotheses' names
398  *
399  * Gets available hypotheses or algorithm in accordance with input parameters
400  */
401 //================================================================================
402 void SMESHGUI_MeshOp::availableHyps( const int theDim,
403                                      const int theHypType,
404                                      QStringList& theHyps ) const
405 {
406   theHyps.clear();
407   QStringList aHypTypeNameList = SMESH::GetAvailableHypotheses(
408     theHypType == Algo , theDim, theHypType == AddHyp );
409   QStringList::const_iterator anIter;
410   for ( anIter = aHypTypeNameList.begin(); anIter != aHypTypeNameList.end(); ++anIter )
411   {
412     HypothesisData* aData = SMESH::GetHypothesisData( *anIter );
413     theHyps.append( aData->Label );
414   }
415 }
416
417 //================================================================================
418 /*!
419  * \brief Gets existing hypotheses or algorithms
420   * \param theDim - specifies dimension of returned hypotheses/algorifms
421   * \param theHypType - specifies whether algorims or hypotheses or additional ones
422   * are retrieved (possible values are in HypType enumeration)
423   * \param theFather - start object for finding ( may be component, mesh, or sub-mesh )
424   * \param theHyps - output list of names.
425   * \param theHypVars - output list of variables.
426  *
427  * Gets existing (i.e. already created) hypotheses or algorithm in accordance with
428  * input parameters
429  */
430 //================================================================================
431 void SMESHGUI_MeshOp::existingHyps( const int theDim,
432                                     const int theHypType,
433                                     _PTR(SObject) theFather,
434                                     QStringList& theHyps,
435                                     QValueList<SMESH::SMESH_Hypothesis_var>& theHypVars )
436 {
437   // Clear hypoheses list
438   theHyps.clear();
439   theHypVars.clear();
440
441   if ( !theFather )
442     return;
443
444   _PTR(SObject)          aHypRoot;
445   _PTR(GenericAttribute) anAttr;
446   _PTR(AttributeName)    aName;
447   _PTR(AttributeIOR)     anIOR;
448
449   bool isMesh = !_CAST( SComponent, theFather );
450   int aPart = -1;
451   if ( isMesh )
452     aPart = theHypType == Algo ? 3 : 2;
453   else
454     aPart = theHypType == Algo ? 2 : 1;
455
456   if ( theFather->FindSubObject( aPart, aHypRoot ) )
457   {
458     _PTR(ChildIterator) anIter =
459       SMESH::GetActiveStudyDocument()->NewChildIterator( aHypRoot );
460     for (; anIter->More(); anIter->Next() )
461     {
462       _PTR(SObject) anObj = anIter->Value();
463       if ( isMesh ) // i.e. mesh or submesh
464       {
465         _PTR(SObject) aRefObj;
466         if ( anObj->ReferencedObject( aRefObj ) )
467           anObj = aRefObj;
468         else
469           continue;
470       }
471       if ( anObj->FindAttribute( anAttr, "AttributeName" ) )
472       {
473         aName = anAttr;
474         CORBA::Object_var aVar = _CAST(SObject,anObj)->GetObject();
475         if ( !CORBA::is_nil( aVar ) )
476         {
477           SMESH::SMESH_Hypothesis_var aHypVar = SMESH::SMESH_Hypothesis::_narrow( aVar );
478           if ( !aHypVar->_is_nil() )
479           {
480             QString aHypType( aHypVar->GetName() );
481             HypothesisData* aData = SMESH::GetHypothesisData( aHypType );
482             if ( ( theDim == -1 || aData->Dim.contains( theDim ) ) &&
483                  ( theHypType == AddHyp ) == aData->IsAux )
484             {
485               theHyps.append( aName->Value().c_str() );
486               theHypVars.append( aHypVar );
487             }
488           }
489         }
490       }
491     }
492   }
493 }
494
495 //================================================================================
496 /*!
497  * \brief Calls plugin methods for hypothesis creation
498   * \param theHypType - specifies whether main hypotheses or additional ones
499   * are created
500   * \param theIndex - index of type of hypothesis to be cerated
501  *
502  * Speicfies dimension of hypothesis to be created (using sender() method), specifies
503  * its type and calls plugin methods for hypothesis creation
504  */
505 //================================================================================
506 void SMESHGUI_MeshOp::onCreateHyp( const int theHypType, const int theIndex )
507 {
508   // Speicfies dimension of hypothesis to be created
509   const QObject* aSender = sender();
510   int aDim = -1;
511   for ( int i = SMESH::DIM_1D; i <= SMESH::DIM_3D; i++ )
512     if ( aSender == myDlg->tab( i ) )
513       aDim = i;
514   if ( aDim == -1 )
515     return;
516
517   // Speicfies type of hypothesis to be created
518   QStringList aHypTypeNames = SMESH::GetAvailableHypotheses( false , aDim, theHypType == AddHyp );
519   if ( theIndex < 0 || theIndex >= aHypTypeNames.count() )
520     return;
521
522   QString aHypTypeName = aHypTypeNames[ theIndex ];
523   HypothesisData* aData = SMESH::GetHypothesisData( aHypTypeName.latin1() );
524   if ( aData == 0 )
525     return;
526
527   QString aClientLibName = aData->ClientLibName;
528   QStringList anOldHyps;
529   _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
530   existingHyps( aDim, theHypType, aFather, anOldHyps, myExistingHyps[ aDim ][ theHypType ] );
531
532   if ( aClientLibName == "" )
533   {
534     // Call hypothesis creation server method (without GUI)
535     QString aHypName = aData->Label;
536     SMESH::CreateHypothesis( aHypTypeName, aHypName, false );
537   }
538   else
539   {
540     // Get hypotheses creator client (GUI)
541     SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator( aHypTypeName );
542
543     // Create hypothesis
544     aCreator->CreateHypothesis( false, myDlg );
545   }
546
547   QStringList aNewHyps;
548   aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
549   existingHyps( aDim, theHypType, aFather, aNewHyps, myExistingHyps[ aDim ][ theHypType ] );
550   if ( aNewHyps.count() > anOldHyps.count() )
551   {
552     for ( int i = anOldHyps.count(); i < aNewHyps.count(); i++ )
553       myDlg->tab( aDim )->addHyp( theHypType, aNewHyps[ i ] );
554   }
555 }
556
557 //================================================================================
558 /*!
559  * \brief Calls plugin methods for hypothesis editing
560   * \param theHypType - specifies whether main hypothesis or additional one
561   * is edited
562   * \param theIndex - index of existing hypothesis
563  *
564  * Calls plugin methods for hypothesis editing
565  */
566 //================================================================================
567 void SMESHGUI_MeshOp::onEditHyp( const int theHypType, const int theIndex )
568 {
569   // Speicfies dimension of hypothesis to be created
570   const QObject* aSender = sender();
571   int aDim = -1;
572   for ( int i = SMESH::DIM_1D; i <= SMESH::DIM_3D; i++ )
573     if ( aSender == myDlg->tab( i ) )
574       aDim = i;
575   if ( aDim == -1 )
576     return;
577
578   QValueList<SMESH::SMESH_Hypothesis_var> aList = myExistingHyps[ aDim ][ theHypType ];
579   SMESH::SMESH_Hypothesis_var aHyp = aList[ theIndex - 1 ];
580   if ( aHyp->_is_nil() )
581     return;
582
583   char* aTypeName = aHyp->GetName();
584   SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator( aTypeName );
585   if ( aCreator )
586     aCreator->EditHypothesis( aHyp );
587 }
588
589 //================================================================================
590 /*!
591  * \brief Creates and selects hypothesis of hypotheses set 
592   * \param theSetName - The name of hypotheses set
593  */
594 //================================================================================
595
596 void SMESHGUI_MeshOp::onHypoSet( const QString& theSetName )
597 {
598   HypothesesSet* aHypoSet = SMESH::GetHypothesesSet( theSetName );
599   if ( !aHypoSet ) return;
600
601   for ( int aHypType = Algo; aHypType < AddHyp; aHypType++ )
602   {
603     bool isAlgo = (aHypType == Algo);
604
605     // clear all hyps
606     for ( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ )
607       setCurrentHyp( dim, aHypType, -1 );
608
609     // set hyps from the set
610     
611     QStringList* aHypoList = isAlgo ? & aHypoSet->AlgoList : & aHypoSet->HypoList;
612     for ( int i = 0, n = aHypoList->count(); i < n; i++ )
613     {
614       const QString& aHypoTypeName = (*aHypoList)[ i ];
615       HypothesisData* aHypData = SMESH::GetHypothesisData( aHypoTypeName );
616       int aDim = aHypData->Dim[0];
617       // create or/and set
618       int index = -1;
619       if ( isAlgo )
620       {
621         QStringList aHypTypeNameList = SMESH::GetAvailableHypotheses( isAlgo, aDim );
622         index = aHypTypeNameList.findIndex( aHypoTypeName );
623         if ( index < 0 ) continue;
624         setCurrentHyp ( aDim, aHypType, index );
625       }
626       else
627       {
628         // try to find an existing hypo
629         QValueList<SMESH::SMESH_Hypothesis_var> & aList = myExistingHyps[ aDim ][ aHypType ];
630         int iHyp = 0, nbHyp = aList.count();
631         for ( ; iHyp < nbHyp; ++iHyp )
632         {
633           SMESH::SMESH_Hypothesis_var aHyp = aList[ iHyp ];
634           if ( !aHyp->_is_nil() && aHypoTypeName == aHyp->GetName() ) {
635             index = iHyp;
636             break;
637           }
638         }
639         if ( index >= 0 ) // found
640         {
641           setCurrentHyp ( aDim, aHypType, index );
642         }
643         else
644         {
645           // silently create a hypothesis
646           SMESH::CreateHypothesis( aHypoTypeName, aHypData->Label, isAlgo );
647           QStringList aNewHyps;
648           _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
649           existingHyps( aDim, aHypType, aFather, aNewHyps, aList );
650           if ( aList.count() > nbHyp )
651           {
652             for ( int i = nbHyp; i < aNewHyps.count(); i++ )
653               myDlg->tab( aDim )->addHyp( aHypType, aNewHyps[ i ] );
654           }
655         }
656       }
657     } // loop on hypos in the set
658   } // loop on algo/hypo
659 }
660
661 //================================================================================
662 /*!
663  * \brief Creates mesh
664   * \param theMess - Output parameter intended for returning error message
665   * \retval bool  - TRUE if mesh is created, FALSE otherwise
666  *
667  * Creates mesh
668  */
669 //================================================================================
670 bool SMESHGUI_MeshOp::createMesh( QString& theMess )
671 {
672   theMess = "";
673
674   QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
675   _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
676   GEOM::GEOM_Object_var aGeomVar =
677     GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
678
679   SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen();
680   if ( aSMESHGen->_is_nil() )
681     return false;
682
683   SUIT_OverrideCursor aWaitCursor;
684
685   // create mesh
686   SMESH::SMESH_Mesh_var aMeshVar = aSMESHGen->CreateMesh( aGeomVar );
687   if ( aMeshVar->_is_nil() )
688     return false;
689   _PTR(SObject) aMeshSO = SMESH::FindSObject( aMeshVar.in() );
690   if ( aMeshSO )
691     SMESH::SetName( aMeshSO, myDlg->objectText( SMESHGUI_MeshDlg::Obj ).latin1() );
692
693   for ( int aDim = SMESH::DIM_1D; aDim <= SMESH::DIM_3D; aDim++ )
694   {
695     if ( !isAccessibleDim( aDim )) continue;
696
697     // assign hypotheses
698     for ( int aHypType = MainHyp; aHypType <= AddHyp; aHypType++ )
699     {
700       int aHypIndex = currentHyp( aDim, aHypType );
701       if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() )
702       {
703         SMESH::SMESH_Hypothesis_var aHypVar = myExistingHyps[ aDim ][ aHypType ][ aHypIndex ];
704         if ( !aHypVar->_is_nil() )
705           SMESH::AddHypothesisOnMesh( aMeshVar, aHypVar );
706       }
707     }
708     // find or create algorithm
709     SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( aDim );
710     if ( !anAlgoVar->_is_nil() )
711       SMESH::AddHypothesisOnMesh( aMeshVar, anAlgoVar );
712   }
713   return true;
714 }
715
716 //================================================================================
717 /*!
718  * \brief Creates sub-mesh
719   * \param theMess - Output parameter intended for returning error message
720   * \retval bool  - TRUE if sub-mesh is created, FALSE otherwise
721  *
722  * Creates sub-mesh
723  */
724 //================================================================================
725 bool SMESHGUI_MeshOp::createSubMesh( QString& theMess )
726 {
727   theMess = "";
728
729   SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen();
730   if ( aSMESHGen->_is_nil() )
731     return false;
732
733   // get mesh object
734   QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
735   _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.latin1() );
736   SMESH::SMESH_Mesh_var aMeshVar =
737     SMESH::SMESH_Mesh::_narrow( _CAST( SObject,pMesh )->GetObject() );
738
739   // get geom object
740   QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
741   _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
742   GEOM::GEOM_Object_var aGeomVar =
743     GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
744
745   SUIT_OverrideCursor aWaitCursor;
746
747   // create sub-mesh
748   QString aName = myDlg->objectText( SMESHGUI_MeshDlg::Obj );
749   SMESH::SMESH_subMesh_var aSubMeshVar = aMeshVar->GetSubMesh( aGeomVar, aName.latin1() );
750
751   for ( int aDim = SMESH::DIM_1D; aDim <= SMESH::DIM_3D; aDim++ )
752   {
753     if ( !isAccessibleDim( aDim )) continue;
754
755     // find or create algorithm
756     SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( aDim );
757     if ( !anAlgoVar->_is_nil() )
758       SMESH::AddHypothesisOnSubMesh( aSubMeshVar, anAlgoVar );
759     // assign hypotheses
760     for ( int aHypType = MainHyp; aHypType <= AddHyp; aHypType++ )
761     {
762       int aHypIndex = currentHyp( aDim, aHypType );
763       if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() )
764       {
765         SMESH::SMESH_Hypothesis_var aHypVar =
766           myExistingHyps[ aDim ][ aHypType ][ aHypIndex ];
767         if ( !aHypVar->_is_nil() )
768           SMESH::AddHypothesisOnSubMesh( aSubMeshVar, aHypVar );
769       }
770     }
771   }
772   return true;
773 }
774
775 //================================================================================
776 /*!
777  * \brief Gets current hypothesis or algorithms
778   * \param theDim - dimension of hypothesis or algorithm
779   * \param theHypType - Type of hypothesis (Algo, MainHyp, AddHyp)
780   * \retval int - current hypothesis or algorithms
781  *
782  * Gets current hypothesis or algorithms
783  */
784 //================================================================================
785 int SMESHGUI_MeshOp::currentHyp( const int theDim, const int theHypType ) const
786 {
787   return myDlg->tab( theDim )->currentHyp( theHypType ) - 1;
788 }
789
790 //================================================================================
791 /*!
792  * \brief Returns true if hypotheses of given dim can be assigned
793   * \param theDim - hypotheses dimension
794   * \retval bool - result
795  */
796 //================================================================================
797 bool SMESHGUI_MeshOp::isAccessibleDim( const int theDim) const
798 {
799   return myDlg->tab( theDim )->isEnabled();
800 }
801
802 //================================================================================
803 /*!
804  * \brief Sets current hypothesis or algorithms
805   * \param theDim - dimension of hypothesis or algorithm
806   * \param theHypType - Type of hypothesis (Algo, MainHyp, AddHyp)
807   * \param theIndex - Index of hypothesis
808  *
809  * Gets current hypothesis or algorithms
810  */
811 //================================================================================
812 void SMESHGUI_MeshOp::setCurrentHyp( const int theDim,
813                                      const int theHypType,
814                                      const int theIndex )
815 {
816   myDlg->tab( theDim )->setCurrentHyp( theHypType, theIndex + 1 );
817 }
818
819 //================================================================================
820 /*!
821  * \brief Generates default and sets mesh/submesh name
822  *
823  * Generates and sets default mesh/submesh name(Mesh_1, Mesh_2, etc.)
824  */
825 //================================================================================
826 void SMESHGUI_MeshOp::setDefaultName() const
827 {
828   QString aResName;
829
830   _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
831   int i = 1;
832   QString aPrefix = tr( myIsMesh ? "SMESH_OBJECT_MESH" : "SMESH_SUBMESH" ) + "_";
833   _PTR(SObject) anObj;
834   do
835   {
836     aResName = aPrefix + QString::number( i++ );
837     anObj = aStudy->FindObject( aResName.latin1() );
838   }
839   while ( anObj );
840
841   QLineEdit* aControl = ( QLineEdit* )myDlg->objectWg(
842     SMESHGUI_MeshDlg::Obj, SMESHGUI_MeshDlg::Control );
843   aControl->setText( aResName );
844 }
845
846 //================================================================================
847 /*!
848  * \brief Gets algorithm or creates it if necessary
849   * \param theDim - specifies dimension of returned hypotheses/algorifms
850   * \retval SMESH::SMESH_Hypothesis_var - algorithm
851  *
852  * Gets algorithm or creates it if necessary
853  */
854 //================================================================================
855 SMESH::SMESH_Hypothesis_var SMESHGUI_MeshOp::getAlgo( const int theDim )
856 {
857   SMESH::SMESH_Hypothesis_var anAlgoVar;
858   int aHypIndex = currentHyp( theDim, Algo );
859   QStringList aHypTypeNameList = SMESH::GetAvailableHypotheses( true, theDim, false );
860   if ( aHypIndex < 0 || aHypIndex >= aHypTypeNameList.count() )
861     return anAlgoVar;
862   QString aHypName = aHypTypeNameList[ aHypIndex ];
863   QValueList<SMESH::SMESH_Hypothesis_var>& aHypVarList = myExistingHyps[ theDim ][ Algo ];
864   QValueList<SMESH::SMESH_Hypothesis_var>::iterator anIter;
865   for ( anIter = aHypVarList.begin(); anIter != aHypVarList.end(); anIter++ )
866   {
867     SMESH::SMESH_Hypothesis_var aHypVar = *anIter;
868     if ( !aHypVar->_is_nil() && aHypName == aHypVar->GetName() )
869     {
870       anAlgoVar = aHypVar;
871       break;
872     }
873   }
874   if ( anAlgoVar->_is_nil() )
875   {
876     HypothesisData* aHypData = SMESH::GetHypothesisData( aHypName );
877     if ( aHypData )
878     {
879       QString aClientLibName = aHypData->ClientLibName;
880       if ( aClientLibName == "" )
881         SMESH::CreateHypothesis( aHypName, aHypData->Label, true );
882       else
883       {
884         SMESHGUI_GenericHypothesisCreator* aCreator =
885           SMESH::GetHypothesisCreator( aHypName );
886         if ( aCreator )
887           aCreator->CreateHypothesis( true, myDlg );
888       }
889       QStringList tmpList;
890       _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
891       existingHyps( theDim, Algo, aFather, tmpList, myExistingHyps[ theDim ][ Algo ] );
892     }
893
894     QValueList<SMESH::SMESH_Hypothesis_var>& aNewHypVarList = myExistingHyps[ theDim ][ Algo ];
895     for ( anIter = aNewHypVarList.begin(); anIter != aNewHypVarList.end(); ++anIter )
896     {
897       SMESH::SMESH_Hypothesis_var aHypVar = *anIter;
898       if ( !aHypVar->_is_nil() && aHypName == aHypVar->GetName() )
899       {
900         anAlgoVar = aHypVar;
901         break;
902       }
903     }
904   }
905
906   return anAlgoVar._retn();
907 }
908
909 //================================================================================
910 /*!
911  * \brief Reads parameters of edited mesh and assigns them to the dialog
912  *
913  * Reads parameters of edited mesh and assigns them to the dialog (called when
914  * mesh is edited only)
915  */
916 //================================================================================
917 void SMESHGUI_MeshOp::readMesh()
918 {
919   QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
920   _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.latin1() );
921   if ( !pObj )
922     return;
923
924   // Get name of mesh if current object is sub-mesh
925   SMESH::SMESH_subMesh_var aSubMeshVar =
926       SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() );
927   if ( !aSubMeshVar->_is_nil() )
928   {
929     SMESH::SMESH_Mesh_var aMeshVar =  aSubMeshVar->GetFather();
930     if ( !aMeshVar->_is_nil() )
931     {
932       _PTR(SObject) aMeshSO = SMESH::FindSObject( aMeshVar );
933       QString aMeshName = name( aMeshSO );
934       myDlg->setObjectText( SMESHGUI_MeshDlg::Mesh, aMeshName );
935     }
936   }
937
938   // Get name of geometry object
939   GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj );
940   if ( !aGeomVar->_is_nil() )
941   {
942     _PTR(SObject) aGeomSO = studyDS()->FindObjectID( aGeomVar->GetStudyEntry() );
943     QString aShapeName = name( aGeomSO );
944     myDlg->setObjectText( SMESHGUI_MeshDlg::Geom, aShapeName );
945   }
946
947   // Get hypotheses and algorithms assigned to the mesh/sub-mesh
948   for ( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ )
949   {
950     // get algorithm
951     QStringList anExisting;
952     int aHypIndex = -1;
953     existingHyps( dim, Algo, pObj, anExisting, myObjHyps[ dim ][ Algo ] );
954     if ( myObjHyps[ dim ][ Algo ].count() > 0 )
955     {
956       SMESH::SMESH_Hypothesis_var aVar = myObjHyps[ dim ][ Algo ].first();
957       QString aHypTypeName = aVar->GetName();
958
959       QStringList aHypTypeNameList = SMESH::GetAvailableHypotheses( true , dim, false );
960       for ( int i = 0, n = aHypTypeNameList.count(); i < n; i++ )
961         if ( aHypTypeName == aHypTypeNameList[ i ] )
962         {
963           aHypIndex = i;
964           break;
965         }
966     }
967     setCurrentHyp( dim, Algo, aHypIndex );
968
969     // get hypotheses
970     for ( int hypType = MainHyp; hypType <= AddHyp; hypType++ )
971     {
972       // get hypotheses
973       existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] );
974       // find index of requered hypothesis among existing ones for this dimension
975       // and hyp types
976       int aHypIndex = -1;
977       if ( myObjHyps[ dim ][ hypType ].count() > 0 )
978         aHypIndex = find( myObjHyps[ dim ][ hypType ].first(),
979                           myExistingHyps[ dim ][ hypType ] );
980       setCurrentHyp( dim, hypType, aHypIndex );
981     }
982   }
983 }
984
985 //================================================================================
986 /*!
987  * \brief Gets name of object
988   * \param theSO - SObject
989   * \retval QString - name of object
990  *
991  * Gets name of object
992  */
993 //================================================================================
994 QString SMESHGUI_MeshOp::name( _PTR(SObject) theSO ) const
995 {
996   QString aResName;
997   if ( theSO )
998   {
999     _PTR(GenericAttribute) anAttr;
1000     _PTR(AttributeName)    aNameAttr;
1001     if ( theSO->FindAttribute( anAttr, "AttributeName" ) )
1002     {
1003       aNameAttr = anAttr;
1004       aResName = aNameAttr->Value().c_str();
1005     }
1006   }
1007   return aResName;
1008 }
1009
1010 //================================================================================
1011 /*!
1012  * \brief Finds hypothesis in input list
1013   * \param theHyp - hypothesis to be found
1014   * \param theHypList - input list of hypotheses
1015   * \retval int - index of hypothesis or -1 if it is not found
1016  *
1017  * Finds position of hypothesis in input list
1018  */
1019 //================================================================================
1020 int SMESHGUI_MeshOp::find( const SMESH::SMESH_Hypothesis_var& theHyp,
1021                            const QValueList<SMESH::SMESH_Hypothesis_var>& theHypList ) const
1022 {
1023   int aRes = -1;
1024   if ( !theHyp->_is_nil() )
1025   {
1026     int i = 0;
1027     QValueList<SMESH::SMESH_Hypothesis_var>::const_iterator anIter;
1028     for ( anIter = theHypList.begin(); anIter != theHypList.end(); ++ anIter )
1029     {
1030       if ( theHyp->_is_equivalent( *anIter ) )
1031       {
1032         aRes = i;
1033         break;
1034       }
1035       i++;
1036     }
1037   }
1038   return aRes;
1039 }
1040
1041 //================================================================================
1042 /*!
1043  * \brief Edits mesh or sub-mesh
1044   * \param theMess - Output parameter intended for returning error message
1045   * \retval bool  - TRUE if mesh is edited succesfully, FALSE otherwise
1046  *
1047  * Assigns new name hypotheses and algoriths to the mesh or sub-mesh
1048  */
1049 //================================================================================
1050 bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess )
1051 {
1052   theMess = "";
1053
1054   SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen();
1055   if ( aSMESHGen->_is_nil() )
1056     return false;
1057
1058   QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
1059   _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.latin1() );
1060   if ( !pObj )
1061     return false;
1062
1063   SUIT_OverrideCursor aWaitCursor;
1064
1065   // Set new name
1066   SMESH::SetName( pObj, myDlg->objectText( SMESHGUI_MeshDlg::Obj ).latin1() );
1067
1068   // Assign new hypotheses and algorithms
1069   for ( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ )
1070   {
1071     if ( !isAccessibleDim( dim )) continue;
1072
1073     // find or create algorithm
1074     bool toDelete = false, toAdd = true;
1075     SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( dim );
1076     if ( anAlgoVar->_is_nil() ) {
1077       toAdd = false;
1078     }
1079     if ( myObjHyps[ dim ][ Algo ].count() > 0 ) {
1080       SMESH::SMESH_Hypothesis_var anOldAlgo = myObjHyps[ dim ][ Algo ].first();
1081       if ( toAdd ) {
1082         if ( strcmp(anOldAlgo->GetName(), anAlgoVar->GetName()) == 0 ) {
1083           toAdd = false;
1084         } else {
1085           toDelete = true;
1086         }
1087       } else {
1088         toDelete = true;
1089       }
1090     }
1091     // remove old algorithm
1092     if ( toDelete )
1093       SMESH::RemoveHypothesisOrAlgorithmOnMesh
1094         ( pObj, myObjHyps[ dim ][ Algo ].first() );
1095
1096     // assign new algorithm
1097     if ( toAdd ) {
1098       SMESH::SMESH_Mesh_var aMeshVar =
1099         SMESH::SMESH_Mesh::_narrow( _CAST(SObject,pObj)->GetObject() );
1100       bool isMesh = !aMeshVar->_is_nil();
1101       if ( isMesh ) {
1102         SMESH::AddHypothesisOnMesh( aMeshVar, anAlgoVar );
1103       } else {
1104         SMESH::SMESH_subMesh_var aVar =
1105           SMESH::SMESH_subMesh::_narrow( _CAST(SObject,pObj)->GetObject() );
1106         if ( !aVar->_is_nil() )
1107           SMESH::AddHypothesisOnSubMesh( aVar, anAlgoVar );
1108       }
1109     }
1110
1111     // assign hypotheses
1112     for ( int hypType = MainHyp; hypType <= AddHyp; hypType++ )
1113     {
1114       int aNewHypIndex = currentHyp( dim, hypType );
1115       int anOldHypIndex = -1;
1116       if ( myObjHyps[ dim ][ hypType ].count() > 0 )
1117         anOldHypIndex = find( myObjHyps[ dim ][ hypType ].first(),
1118                               myExistingHyps[ dim ][ hypType ] );
1119       if ( aNewHypIndex != anOldHypIndex )
1120       {
1121         // remove old hypotheses
1122         if ( anOldHypIndex >= 0 )
1123           SMESH::RemoveHypothesisOrAlgorithmOnMesh(
1124             pObj, myExistingHyps[ dim ][ hypType ][ anOldHypIndex ] );
1125
1126         // assign new hypotheses
1127         if ( aNewHypIndex != -1 )
1128         {
1129           SMESH::SMESH_Mesh_var aMeshVar =
1130               SMESH::SMESH_Mesh::_narrow( _CAST(SObject,pObj)->GetObject() );
1131           bool isMesh = !aMeshVar->_is_nil();
1132           if ( isMesh )
1133           {
1134             SMESH::AddHypothesisOnMesh(
1135               aMeshVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ] );
1136           }
1137           else
1138           {
1139             SMESH::SMESH_subMesh_var aVar =
1140               SMESH::SMESH_subMesh::_narrow( _CAST(SObject,pObj)->GetObject() );
1141             if ( !aVar->_is_nil() )
1142               SMESH::AddHypothesisOnSubMesh(
1143                 aVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ] );
1144           }
1145         }
1146         // reread all hypotheses of mesh if necessary
1147         QStringList anExisting;
1148         existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] );
1149       }
1150     }
1151   }
1152
1153   return true;
1154 }
1155
1156 //================================================================================
1157 /*!
1158  * \brief Verifies whether given operator is valid for this one
1159   * \param theOtherOp - other operation
1160   * \return Returns TRUE if the given operator is valid for this one, FALSE otherwise
1161 *
1162 * method redefined from base class verifies whether given operator is valid for
1163 * this one (i.e. can be started "above" this operator). In current implementation method
1164 * retuns false if theOtherOp operation is not intended for deleting objects or mesh
1165 * elements.
1166 */
1167 //================================================================================
1168 bool SMESHGUI_MeshOp::isValid( SUIT_Operation* theOp ) const
1169 {
1170   return SMESHGUI_Operation::isValid( theOp ) && !theOp->inherits( "SMESHGUI_MeshOp" );
1171 }