Salome HOME
c5b03f9b08076bbef387363b18d8a88ab1861f4a
[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   if ( myToCreate )
280   {
281     try
282     {
283       QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
284       _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
285       if ( pGeom ) {
286         GEOM::GEOM_Object_var aGeomVar =
287           GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
288         if ( !aGeomVar->_is_nil() ) {
289           shapeDim = 0;
290           switch ( aGeomVar->GetShapeType() ) {
291           case GEOM::SOLID:
292           case GEOM::SHELL:  shapeDim = 3; break;
293           case GEOM::FACE:   shapeDim = 2; break;
294           case GEOM::WIRE:   
295           case GEOM::EDGE:   shapeDim = 1; break;
296           case GEOM::VERTEX: shapeDim = 0; break;
297           default:
298             TopoDS_Shape aShape;
299             if ( GEOMBase::GetShape(aGeomVar, aShape)) {
300               TopExp_Explorer exp( aShape, TopAbs_SHELL );
301               if ( exp.More() )
302                 shapeDim = 3;
303               else if ( exp.Init( aShape, TopAbs_FACE ), exp.More() )
304                 shapeDim = 2;
305               else if ( exp.Init( aShape, TopAbs_EDGE ), exp.More() )
306                 shapeDim = 1;
307               else
308                 shapeDim = 0;
309             }
310           }
311         }
312       }
313     }
314     catch ( const SALOME::SALOME_Exception& S_ex )
315     {
316       SalomeApp_Tools::QtCatchCorbaException( S_ex );
317     }
318     catch ( ... )
319     {
320     }
321   }
322   myDlg->setMaxHypoDim( shapeDim );
323 }
324
325 //================================================================================
326 /*!
327  * \brief Verifies validity of input data
328   * \param theMess - Output parameter intended for returning error message
329   * \retval bool  - TRUE if input data is valid, false otherwise
330  *
331  * Verifies validity of input data. This method is called when "Apply" or "OK" button
332  * is pressed before mesh creation or editing.
333  */
334 //================================================================================
335 bool SMESHGUI_MeshOp::isValid( QString& theMess ) const
336 {
337   // Selected object to be  edited
338   if ( !myToCreate && myDlg->selectedObject( SMESHGUI_MeshDlg::Obj ) == "" )
339   {
340     theMess = tr( "THERE_IS_NO_OBJECT_FOR_EDITING" );
341     return false;
342   }
343
344   // Name
345   QString aMeshName = myDlg->objectText( SMESHGUI_MeshDlg::Obj );
346   aMeshName = aMeshName.stripWhiteSpace();
347   if ( aMeshName == "" )
348   {
349     theMess = myIsMesh ? tr( "NAME_OF_MESH_IS_EMPTY" ) : tr( "NAME_OF_SUBMESH_IS_EMPTY" );
350     return false;
351   }
352
353   // Geom
354   if ( myToCreate )
355   {
356     QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
357     if ( aGeomEntry == "" )
358     {
359       theMess = tr( "GEOMETRY_OBJECT_IS_NOT_DEFINED" );
360       return false;
361     }
362     _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
363     if ( !pGeom || GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() )->_is_nil() )
364     {
365       theMess = tr( "GEOMETRY_OBJECT_IS_NULL" );
366       return false;
367     }
368
369     // Mesh
370     if ( !myIsMesh ) // i.e sub-mesh creation,
371     {
372       QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
373       if ( aMeshEntry == "" )
374       {
375         theMess = tr( "MESH_IS_NOT_DEFINED" );
376         return false;
377       }
378       _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.latin1() );
379       if ( !pMesh || SMESH::SMESH_Mesh::_narrow( _CAST( SObject,pMesh )->GetObject() )->_is_nil() )
380       {
381         theMess = tr( "MESH_IS_NULL" );
382         return false;
383       }
384     }
385   }
386   return true;
387 }
388
389 //================================================================================
390 /*!
391  * \brief Gets available hypotheses or algorithms
392   * \param theDim - specifies dimension of returned hypotheses/algorifms
393   * \param theHypType - specifies whether algorims or hypotheses or additional ones
394   * are retrieved (possible values are in HypType enumeration)
395   * \param theHyps - Output list of hypotheses' names
396  *
397  * Gets available hypotheses or algorithm in accordance with input parameters
398  */
399 //================================================================================
400 void SMESHGUI_MeshOp::availableHyps( const int theDim,
401                                      const int theHypType,
402                                      QStringList& theHyps ) const
403 {
404   theHyps.clear();
405   QStringList aHypTypeNameList = SMESH::GetAvailableHypotheses(
406     theHypType == Algo , theDim, theHypType == AddHyp );
407   QStringList::const_iterator anIter;
408   for ( anIter = aHypTypeNameList.begin(); anIter != aHypTypeNameList.end(); ++anIter )
409   {
410     HypothesisData* aData = SMESH::GetHypothesisData( *anIter );
411     theHyps.append( aData->Label );
412   }
413 }
414
415 //================================================================================
416 /*!
417  * \brief Gets existing hypotheses or algorithms
418   * \param theDim - specifies dimension of returned hypotheses/algorifms
419   * \param theHypType - specifies whether algorims or hypotheses or additional ones
420   * are retrieved (possible values are in HypType enumeration)
421   * \param theFather - start object for finding ( may be component, mesh, or sub-mesh )
422   * \param theHyps - output list of names.
423   * \param theHypVars - output list of variables.
424  *
425  * Gets existing (i.e. already created) hypotheses or algorithm in accordance with
426  * input parameters
427  */
428 //================================================================================
429 void SMESHGUI_MeshOp::existingHyps( const int theDim,
430                                     const int theHypType,
431                                     _PTR(SObject) theFather,
432                                     QStringList& theHyps,
433                                     QValueList<SMESH::SMESH_Hypothesis_var>& theHypVars )
434 {
435   // Clear hypoheses list
436   theHyps.clear();
437   theHypVars.clear();
438
439   if ( !theFather )
440     return;
441
442   _PTR(SObject)          aHypRoot;
443   _PTR(GenericAttribute) anAttr;
444   _PTR(AttributeName)    aName;
445   _PTR(AttributeIOR)     anIOR;
446
447   bool isMesh = !_CAST( SComponent, theFather );
448   int aPart = -1;
449   if ( isMesh )
450     aPart = theHypType == Algo ? 3 : 2;
451   else
452     aPart = theHypType == Algo ? 2 : 1;
453
454   if ( theFather->FindSubObject( aPart, aHypRoot ) )
455   {
456     _PTR(ChildIterator) anIter =
457       SMESH::GetActiveStudyDocument()->NewChildIterator( aHypRoot );
458     for (; anIter->More(); anIter->Next() )
459     {
460       _PTR(SObject) anObj = anIter->Value();
461       if ( isMesh ) // i.e. mesh or submesh
462       {
463         _PTR(SObject) aRefObj;
464         if ( anObj->ReferencedObject( aRefObj ) )
465           anObj = aRefObj;
466         else
467           continue;
468       }
469       if ( anObj->FindAttribute( anAttr, "AttributeName" ) )
470       {
471         aName = anAttr;
472         CORBA::Object_var aVar = _CAST(SObject,anObj)->GetObject();
473         if ( !CORBA::is_nil( aVar ) )
474         {
475           SMESH::SMESH_Hypothesis_var aHypVar = SMESH::SMESH_Hypothesis::_narrow( aVar );
476           if ( !aHypVar->_is_nil() )
477           {
478             QString aHypType( aHypVar->GetName() );
479             HypothesisData* aData = SMESH::GetHypothesisData( aHypType );
480             if ( ( theDim == -1 || aData->Dim.contains( theDim ) ) &&
481                  ( theHypType == AddHyp ) == aData->IsAux )
482             {
483               theHyps.append( aName->Value().c_str() );
484               theHypVars.append( aHypVar );
485             }
486           }
487         }
488       }
489     }
490   }
491 }
492
493 //================================================================================
494 /*!
495  * \brief Calls plugin methods for hypothesis creation
496   * \param theHypType - specifies whether main hypotheses or additional ones
497   * are created
498   * \param theIndex - index of type of hypothesis to be cerated
499  *
500  * Speicfies dimension of hypothesis to be created (using sender() method), specifies
501  * its type and calls plugin methods for hypothesis creation
502  */
503 //================================================================================
504 void SMESHGUI_MeshOp::onCreateHyp( const int theHypType, const int theIndex )
505 {
506   // Speicfies dimension of hypothesis to be created
507   const QObject* aSender = sender();
508   int aDim = -1;
509   for ( int i = SMESH::DIM_1D; i <= SMESH::DIM_3D; i++ )
510     if ( aSender == myDlg->tab( i ) )
511       aDim = i;
512   if ( aDim == -1 )
513     return;
514
515   // Speicfies type of hypothesis to be created
516   QStringList aHypTypeNames = SMESH::GetAvailableHypotheses( false , aDim, theHypType == AddHyp );
517   if ( theIndex < 0 || theIndex >= aHypTypeNames.count() )
518     return;
519
520   QString aHypTypeName = aHypTypeNames[ theIndex ];
521   HypothesisData* aData = SMESH::GetHypothesisData( aHypTypeName.latin1() );
522   if ( aData == 0 )
523     return;
524
525   QString aClientLibName = aData->ClientLibName;
526   QStringList anOldHyps;
527   _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
528   existingHyps( aDim, theHypType, aFather, anOldHyps, myExistingHyps[ aDim ][ theHypType ] );
529
530   if ( aClientLibName == "" )
531   {
532     // Call hypothesis creation server method (without GUI)
533     QString aHypName = aData->Label;
534     SMESH::CreateHypothesis( aHypTypeName, aHypName, false );
535   }
536   else
537   {
538     // Get hypotheses creator client (GUI)
539     SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator( aHypTypeName );
540
541     // Create hypothesis
542     aCreator->CreateHypothesis( false, myDlg );
543   }
544
545   QStringList aNewHyps;
546   aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
547   existingHyps( aDim, theHypType, aFather, aNewHyps, myExistingHyps[ aDim ][ theHypType ] );
548   if ( aNewHyps.count() > anOldHyps.count() )
549   {
550     for ( int i = anOldHyps.count(); i < aNewHyps.count(); i++ )
551       myDlg->tab( aDim )->addHyp( theHypType, aNewHyps[ i ] );
552   }
553 }
554
555 //================================================================================
556 /*!
557  * \brief Calls plugin methods for hypothesis editing
558   * \param theHypType - specifies whether main hypothesis or additional one
559   * is edited
560   * \param theIndex - index of existing hypothesis
561  *
562  * Calls plugin methods for hypothesis editing
563  */
564 //================================================================================
565 void SMESHGUI_MeshOp::onEditHyp( const int theHypType, const int theIndex )
566 {
567   // Speicfies dimension of hypothesis to be created
568   const QObject* aSender = sender();
569   int aDim = -1;
570   for ( int i = SMESH::DIM_1D; i <= SMESH::DIM_3D; i++ )
571     if ( aSender == myDlg->tab( i ) )
572       aDim = i;
573   if ( aDim == -1 )
574     return;
575
576   QValueList<SMESH::SMESH_Hypothesis_var> aList = myExistingHyps[ aDim ][ theHypType ];
577   SMESH::SMESH_Hypothesis_var aHyp = aList[ theIndex - 1 ];
578   if ( aHyp->_is_nil() )
579     return;
580
581   char* aTypeName = aHyp->GetName();
582   SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator( aTypeName );
583   if ( aCreator )
584     aCreator->EditHypothesis( aHyp );
585 }
586
587 //================================================================================
588 /*!
589  * \brief Creates and selects hypothesis of hypotheses set 
590   * \param theSetName - The name of hypotheses set
591  */
592 //================================================================================
593
594 void SMESHGUI_MeshOp::onHypoSet( const QString& theSetName )
595 {
596   HypothesesSet* aHypoSet = SMESH::GetHypothesesSet( theSetName );
597   if ( !aHypoSet ) return;
598
599   for ( int aHypType = Algo; aHypType < AddHyp; aHypType++ )
600   {
601     bool isAlgo = (aHypType == Algo);
602
603     // clear all hyps
604     for ( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ )
605       setCurrentHyp( dim, aHypType, -1 );
606
607     // set hyps from the set
608     
609     QStringList* aHypoList = isAlgo ? & aHypoSet->AlgoList : & aHypoSet->HypoList;
610     for ( int i = 0, n = aHypoList->count(); i < n; i++ )
611     {
612       const QString& aHypoTypeName = (*aHypoList)[ i ];
613       HypothesisData* aHypData = SMESH::GetHypothesisData( aHypoTypeName );
614       int aDim = aHypData->Dim[0];
615       // create or/and set
616       int index = -1;
617       if ( isAlgo )
618       {
619         QStringList aHypTypeNameList = SMESH::GetAvailableHypotheses( isAlgo, aDim );
620         index = aHypTypeNameList.findIndex( aHypoTypeName );
621         if ( index < 0 ) continue;
622         setCurrentHyp ( aDim, aHypType, index );
623       }
624       else
625       {
626         // try to find an existing hypo
627         QValueList<SMESH::SMESH_Hypothesis_var> & aList = myExistingHyps[ aDim ][ aHypType ];
628         int iHyp = 0, nbHyp = aList.count();
629         for ( ; iHyp < nbHyp; ++iHyp )
630         {
631           SMESH::SMESH_Hypothesis_var aHyp = aList[ iHyp ];
632           if ( !aHyp->_is_nil() && aHypoTypeName == aHyp->GetName() ) {
633             index = iHyp;
634             break;
635           }
636         }
637         if ( index >= 0 ) // found
638         {
639           setCurrentHyp ( aDim, aHypType, index );
640         }
641         else
642         {
643           // silently create a hypothesis
644           SMESH::CreateHypothesis( aHypoTypeName, aHypData->Label, isAlgo );
645           QStringList aNewHyps;
646           _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
647           existingHyps( aDim, aHypType, aFather, aNewHyps, aList );
648           if ( aList.count() > nbHyp )
649           {
650             for ( int i = nbHyp; i < aNewHyps.count(); i++ )
651               myDlg->tab( aDim )->addHyp( aHypType, aNewHyps[ i ] );
652           }
653         }
654       }
655     } // loop on hypos in the set
656   } // loop on algo/hypo
657 }
658
659 //================================================================================
660 /*!
661  * \brief Creates mesh
662   * \param theMess - Output parameter intended for returning error message
663   * \retval bool  - TRUE if mesh is created, FALSE otherwise
664  *
665  * Creates mesh
666  */
667 //================================================================================
668 bool SMESHGUI_MeshOp::createMesh( QString& theMess )
669 {
670   theMess = "";
671
672   QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
673   _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
674   GEOM::GEOM_Object_var aGeomVar =
675     GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
676
677   SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen();
678   if ( aSMESHGen->_is_nil() )
679     return false;
680
681   SUIT_OverrideCursor aWaitCursor;
682
683   // create mesh
684   SMESH::SMESH_Mesh_var aMeshVar = aSMESHGen->CreateMesh( aGeomVar );
685   if ( aMeshVar->_is_nil() )
686     return false;
687   _PTR(SObject) aMeshSO = SMESH::FindSObject( aMeshVar.in() );
688   if ( aMeshSO )
689     SMESH::SetName( aMeshSO, myDlg->objectText( SMESHGUI_MeshDlg::Obj ).latin1() );
690
691   for ( int aDim = SMESH::DIM_1D; aDim <= SMESH::DIM_3D; aDim++ )
692   {
693     if ( !isAccessibleDim( aDim )) continue;
694
695     // assign hypotheses
696     for ( int aHypType = MainHyp; aHypType <= AddHyp; aHypType++ )
697     {
698       int aHypIndex = currentHyp( aDim, aHypType );
699       if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() )
700       {
701         SMESH::SMESH_Hypothesis_var aHypVar = myExistingHyps[ aDim ][ aHypType ][ aHypIndex ];
702         if ( !aHypVar->_is_nil() )
703           SMESH::AddHypothesisOnMesh( aMeshVar, aHypVar );
704       }
705     }
706     // find or create algorithm
707     SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( aDim );
708     if ( !anAlgoVar->_is_nil() )
709       SMESH::AddHypothesisOnMesh( aMeshVar, anAlgoVar );
710   }
711   return true;
712 }
713
714 //================================================================================
715 /*!
716  * \brief Creates sub-mesh
717   * \param theMess - Output parameter intended for returning error message
718   * \retval bool  - TRUE if sub-mesh is created, FALSE otherwise
719  *
720  * Creates sub-mesh
721  */
722 //================================================================================
723 bool SMESHGUI_MeshOp::createSubMesh( QString& theMess )
724 {
725   theMess = "";
726
727   SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen();
728   if ( aSMESHGen->_is_nil() )
729     return false;
730
731   // get mesh object
732   QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
733   _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.latin1() );
734   SMESH::SMESH_Mesh_var aMeshVar =
735     SMESH::SMESH_Mesh::_narrow( _CAST( SObject,pMesh )->GetObject() );
736
737   // get geom object
738   QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
739   _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
740   GEOM::GEOM_Object_var aGeomVar =
741     GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
742
743   SUIT_OverrideCursor aWaitCursor;
744
745   // create sub-mesh
746   QString aName = myDlg->objectText( SMESHGUI_MeshDlg::Obj );
747   SMESH::SMESH_subMesh_var aSubMeshVar = aMeshVar->GetSubMesh( aGeomVar, aName.latin1() );
748
749   for ( int aDim = SMESH::DIM_1D; aDim <= SMESH::DIM_3D; aDim++ )
750   {
751     if ( !isAccessibleDim( aDim )) continue;
752
753     // find or create algorithm
754     SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( aDim );
755     if ( !anAlgoVar->_is_nil() )
756       SMESH::AddHypothesisOnSubMesh( aSubMeshVar, anAlgoVar );
757     // assign hypotheses
758     for ( int aHypType = MainHyp; aHypType <= AddHyp; aHypType++ )
759     {
760       int aHypIndex = currentHyp( aDim, aHypType );
761       if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() )
762       {
763         SMESH::SMESH_Hypothesis_var aHypVar =
764           myExistingHyps[ aDim ][ aHypType ][ aHypIndex ];
765         if ( !aHypVar->_is_nil() )
766           SMESH::AddHypothesisOnSubMesh( aSubMeshVar, aHypVar );
767       }
768     }
769   }
770   return true;
771 }
772
773 //================================================================================
774 /*!
775  * \brief Gets current hypothesis or algorithms
776   * \param theDim - dimension of hypothesis or algorithm
777   * \param theHypType - Type of hypothesis (Algo, MainHyp, AddHyp)
778   * \retval int - current hypothesis or algorithms
779  *
780  * Gets current hypothesis or algorithms
781  */
782 //================================================================================
783 int SMESHGUI_MeshOp::currentHyp( const int theDim, const int theHypType ) const
784 {
785   return myDlg->tab( theDim )->currentHyp( theHypType ) - 1;
786 }
787
788 //================================================================================
789 /*!
790  * \brief Returns true if hypotheses of given dim can be assigned
791   * \param theDim - hypotheses dimension
792   * \retval bool - result
793  */
794 //================================================================================
795 bool SMESHGUI_MeshOp::isAccessibleDim( const int theDim) const
796 {
797   return myDlg->tab( theDim )->isEnabled();
798 }
799
800 //================================================================================
801 /*!
802  * \brief Sets current hypothesis or algorithms
803   * \param theDim - dimension of hypothesis or algorithm
804   * \param theHypType - Type of hypothesis (Algo, MainHyp, AddHyp)
805   * \param theIndex - Index of hypothesis
806  *
807  * Gets current hypothesis or algorithms
808  */
809 //================================================================================
810 void SMESHGUI_MeshOp::setCurrentHyp( const int theDim,
811                                      const int theHypType,
812                                      const int theIndex )
813 {
814   myDlg->tab( theDim )->setCurrentHyp( theHypType, theIndex + 1 );
815 }
816
817 //================================================================================
818 /*!
819  * \brief Generates default and sets mesh/submesh name
820  *
821  * Generates and sets default mesh/submesh name(Mesh_1, Mesh_2, etc.)
822  */
823 //================================================================================
824 void SMESHGUI_MeshOp::setDefaultName() const
825 {
826   QString aResName;
827
828   _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
829   int i = 1;
830   QString aPrefix = tr( myIsMesh ? "SMESH_OBJECT_MESH" : "SMESH_SUBMESH" ) + "_";
831   _PTR(SObject) anObj;
832   do
833   {
834     aResName = aPrefix + QString::number( i++ );
835     anObj = aStudy->FindObject( aResName.latin1() );
836   }
837   while ( anObj );
838
839   QLineEdit* aControl = ( QLineEdit* )myDlg->objectWg(
840     SMESHGUI_MeshDlg::Obj, SMESHGUI_MeshDlg::Control );
841   aControl->setText( aResName );
842 }
843
844 //================================================================================
845 /*!
846  * \brief Gets algorithm or creates it if necessary
847   * \param theDim - specifies dimension of returned hypotheses/algorifms
848   * \retval SMESH::SMESH_Hypothesis_var - algorithm
849  *
850  * Gets algorithm or creates it if necessary
851  */
852 //================================================================================
853 SMESH::SMESH_Hypothesis_var SMESHGUI_MeshOp::getAlgo( const int theDim )
854 {
855   SMESH::SMESH_Hypothesis_var anAlgoVar;
856   int aHypIndex = currentHyp( theDim, Algo );
857   QStringList aHypTypeNameList = SMESH::GetAvailableHypotheses( true, theDim, false );
858   if ( aHypIndex < 0 || aHypIndex >= aHypTypeNameList.count() )
859     return anAlgoVar;
860   QString aHypName = aHypTypeNameList[ aHypIndex ];
861   QValueList<SMESH::SMESH_Hypothesis_var>& aHypVarList = myExistingHyps[ theDim ][ Algo ];
862   QValueList<SMESH::SMESH_Hypothesis_var>::iterator anIter;
863   for ( anIter = aHypVarList.begin(); anIter != aHypVarList.end(); anIter++ )
864   {
865     SMESH::SMESH_Hypothesis_var aHypVar = *anIter;
866     if ( !aHypVar->_is_nil() && aHypName == aHypVar->GetName() )
867     {
868       anAlgoVar = aHypVar;
869       break;
870     }
871   }
872   if ( anAlgoVar->_is_nil() )
873   {
874     HypothesisData* aHypData = SMESH::GetHypothesisData( aHypName );
875     if ( aHypData )
876     {
877       QString aClientLibName = aHypData->ClientLibName;
878       if ( aClientLibName == "" )
879         SMESH::CreateHypothesis( aHypName, aHypData->Label, true );
880       else
881       {
882         SMESHGUI_GenericHypothesisCreator* aCreator =
883           SMESH::GetHypothesisCreator( aHypName );
884         if ( aCreator )
885           aCreator->CreateHypothesis( true, myDlg );
886       }
887       QStringList tmpList;
888       _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
889       existingHyps( theDim, Algo, aFather, tmpList, myExistingHyps[ theDim ][ Algo ] );
890     }
891
892     QValueList<SMESH::SMESH_Hypothesis_var>& aNewHypVarList = myExistingHyps[ theDim ][ Algo ];
893     for ( anIter = aNewHypVarList.begin(); anIter != aNewHypVarList.end(); ++anIter )
894     {
895       SMESH::SMESH_Hypothesis_var aHypVar = *anIter;
896       if ( !aHypVar->_is_nil() && aHypName == aHypVar->GetName() )
897       {
898         anAlgoVar = aHypVar;
899         break;
900       }
901     }
902   }
903
904   return anAlgoVar._retn();
905 }
906
907 //================================================================================
908 /*!
909  * \brief Reads parameters of edited mesh and assigns them to the dialog
910  *
911  * Reads parameters of edited mesh and assigns them to the dialog (called when
912  * mesh is edited only)
913  */
914 //================================================================================
915 void SMESHGUI_MeshOp::readMesh()
916 {
917   QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
918   _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.latin1() );
919   if ( !pObj )
920     return;
921
922   // Get name of mesh if current object is sub-mesh
923   SMESH::SMESH_subMesh_var aSubMeshVar =
924       SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() );
925   if ( !aSubMeshVar->_is_nil() )
926   {
927     SMESH::SMESH_Mesh_var aMeshVar =  aSubMeshVar->GetFather();
928     if ( !aMeshVar->_is_nil() )
929     {
930       _PTR(SObject) aMeshSO = SMESH::FindSObject( aMeshVar );
931       QString aMeshName = name( aMeshSO );
932       myDlg->setObjectText( SMESHGUI_MeshDlg::Mesh, aMeshName );
933     }
934   }
935
936   // Get name of geometry object
937   GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj );
938   if ( !aGeomVar->_is_nil() )
939   {
940     _PTR(SObject) aGeomSO = studyDS()->FindObjectID( aGeomVar->GetStudyEntry() );
941     QString aShapeName = name( aGeomSO );
942     myDlg->setObjectText( SMESHGUI_MeshDlg::Geom, aShapeName );
943   }
944
945   // Get hypotheses and algorithms assigned to the mesh/sub-mesh
946   for ( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ )
947   {
948     // get algorithm
949     QStringList anExisting;
950     int aHypIndex = -1;
951     existingHyps( dim, Algo, pObj, anExisting, myObjHyps[ dim ][ Algo ] );
952     if ( myObjHyps[ dim ][ Algo ].count() > 0 )
953     {
954       SMESH::SMESH_Hypothesis_var aVar = myObjHyps[ dim ][ Algo ].first();
955       QString aHypTypeName = aVar->GetName();
956
957       QStringList aHypTypeNameList = SMESH::GetAvailableHypotheses( true , dim, false );
958       for ( int i = 0, n = aHypTypeNameList.count(); i < n; i++ )
959         if ( aHypTypeName == aHypTypeNameList[ i ] )
960         {
961           aHypIndex = i;
962           break;
963         }
964     }
965     setCurrentHyp( dim, Algo, aHypIndex );
966
967     // get hypotheses
968     for ( int hypType = MainHyp; hypType <= AddHyp; hypType++ )
969     {
970       // get hypotheses
971       existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] );
972       // find index of requered hypothesis among existing ones for this dimension
973       // and hyp types
974       int aHypIndex = -1;
975       if ( myObjHyps[ dim ][ hypType ].count() > 0 )
976         aHypIndex = find( myObjHyps[ dim ][ hypType ].first(),
977                           myExistingHyps[ dim ][ hypType ] );
978       setCurrentHyp( dim, hypType, aHypIndex );
979     }
980   }
981 }
982
983 //================================================================================
984 /*!
985  * \brief Gets name of object
986   * \param theSO - SObject
987   * \retval QString - name of object
988  *
989  * Gets name of object
990  */
991 //================================================================================
992 QString SMESHGUI_MeshOp::name( _PTR(SObject) theSO ) const
993 {
994   QString aResName;
995   if ( theSO )
996   {
997     _PTR(GenericAttribute) anAttr;
998     _PTR(AttributeName)    aNameAttr;
999     if ( theSO->FindAttribute( anAttr, "AttributeName" ) )
1000     {
1001       aNameAttr = anAttr;
1002       aResName = aNameAttr->Value().c_str();
1003     }
1004   }
1005   return aResName;
1006 }
1007
1008 //================================================================================
1009 /*!
1010  * \brief Finds hypothesis in input list
1011   * \param theHyp - hypothesis to be found
1012   * \param theHypList - input list of hypotheses
1013   * \retval int - index of hypothesis or -1 if it is not found
1014  *
1015  * Finds position of hypothesis in input list
1016  */
1017 //================================================================================
1018 int SMESHGUI_MeshOp::find( const SMESH::SMESH_Hypothesis_var& theHyp,
1019                            const QValueList<SMESH::SMESH_Hypothesis_var>& theHypList ) const
1020 {
1021   int aRes = -1;
1022   if ( !theHyp->_is_nil() )
1023   {
1024     int i = 0;
1025     QValueList<SMESH::SMESH_Hypothesis_var>::const_iterator anIter;
1026     for ( anIter = theHypList.begin(); anIter != theHypList.end(); ++ anIter )
1027     {
1028       if ( theHyp->_is_equivalent( *anIter ) )
1029       {
1030         aRes = i;
1031         break;
1032       }
1033       i++;
1034     }
1035   }
1036   return aRes;
1037 }
1038
1039 //================================================================================
1040 /*!
1041  * \brief Edits mesh or sub-mesh
1042   * \param theMess - Output parameter intended for returning error message
1043   * \retval bool  - TRUE if mesh is edited succesfully, FALSE otherwise
1044  *
1045  * Assigns new name hypotheses and algoriths to the mesh or sub-mesh
1046  */
1047 //================================================================================
1048 bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess )
1049 {
1050   theMess = "";
1051
1052   SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen();
1053   if ( aSMESHGen->_is_nil() )
1054     return false;
1055
1056   QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
1057   _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.latin1() );
1058   if ( !pObj )
1059     return false;
1060
1061   SUIT_OverrideCursor aWaitCursor;
1062
1063   // Set new name
1064   SMESH::SetName( pObj, myDlg->objectText( SMESHGUI_MeshDlg::Obj ).latin1() );
1065
1066   // Assign new hypotheses and algorithms
1067   for ( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ )
1068   {
1069     if ( !isAccessibleDim( dim )) continue;
1070
1071     // find or create algorithm
1072     bool toDelete = false, toAdd = true;
1073     SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( dim );
1074     if ( anAlgoVar->_is_nil() ) {
1075       toAdd = false;
1076     }
1077     if ( myObjHyps[ dim ][ Algo ].count() > 0 ) {
1078       SMESH::SMESH_Hypothesis_var anOldAlgo = myObjHyps[ dim ][ Algo ].first();
1079       if ( toAdd ) {
1080         if ( strcmp(anOldAlgo->GetName(), anAlgoVar->GetName()) == 0 ) {
1081           toAdd = false;
1082         } else {
1083           toDelete = true;
1084         }
1085       } else {
1086         toDelete = true;
1087       }
1088     }
1089     // remove old algorithm
1090     if ( toDelete )
1091       SMESH::RemoveHypothesisOrAlgorithmOnMesh
1092         ( pObj, myObjHyps[ dim ][ Algo ].first() );
1093
1094     // assign new algorithm
1095     if ( toAdd ) {
1096       SMESH::SMESH_Mesh_var aMeshVar =
1097         SMESH::SMESH_Mesh::_narrow( _CAST(SObject,pObj)->GetObject() );
1098       bool isMesh = !aMeshVar->_is_nil();
1099       if ( isMesh ) {
1100         SMESH::AddHypothesisOnMesh( aMeshVar, anAlgoVar );
1101       } else {
1102         SMESH::SMESH_subMesh_var aVar =
1103           SMESH::SMESH_subMesh::_narrow( _CAST(SObject,pObj)->GetObject() );
1104         if ( !aVar->_is_nil() )
1105           SMESH::AddHypothesisOnSubMesh( aVar, anAlgoVar );
1106       }
1107     }
1108
1109     // assign hypotheses
1110     for ( int hypType = MainHyp; hypType <= AddHyp; hypType++ )
1111     {
1112       int aNewHypIndex = currentHyp( dim, hypType );
1113       int anOldHypIndex = -1;
1114       if ( myObjHyps[ dim ][ hypType ].count() > 0 )
1115         anOldHypIndex = find( myObjHyps[ dim ][ hypType ].first(),
1116                               myExistingHyps[ dim ][ hypType ] );
1117       if ( aNewHypIndex != anOldHypIndex )
1118       {
1119         // remove old hypotheses
1120         if ( anOldHypIndex >= 0 )
1121           SMESH::RemoveHypothesisOrAlgorithmOnMesh(
1122             pObj, myExistingHyps[ dim ][ hypType ][ anOldHypIndex ] );
1123
1124         // assign new hypotheses
1125         if ( aNewHypIndex != -1 )
1126         {
1127           SMESH::SMESH_Mesh_var aMeshVar =
1128               SMESH::SMESH_Mesh::_narrow( _CAST(SObject,pObj)->GetObject() );
1129           bool isMesh = !aMeshVar->_is_nil();
1130           if ( isMesh )
1131           {
1132             SMESH::AddHypothesisOnMesh(
1133               aMeshVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ] );
1134           }
1135           else
1136           {
1137             SMESH::SMESH_subMesh_var aVar =
1138               SMESH::SMESH_subMesh::_narrow( _CAST(SObject,pObj)->GetObject() );
1139             if ( !aVar->_is_nil() )
1140               SMESH::AddHypothesisOnSubMesh(
1141                 aVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ] );
1142           }
1143         }
1144         // reread all hypotheses of mesh if necessary
1145         QStringList anExisting;
1146         existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] );
1147       }
1148     }
1149   }
1150
1151   return true;
1152 }
1153
1154 //================================================================================
1155 /*!
1156  * \brief Verifies whether given operator is valid for this one
1157   * \param theOtherOp - other operation
1158   * \return Returns TRUE if the given operator is valid for this one, FALSE otherwise
1159 *
1160 * method redefined from base class verifies whether given operator is valid for
1161 * this one (i.e. can be started "above" this operator). In current implementation method
1162 * retuns false if theOtherOp operation is not intended for deleting objects or mesh
1163 * elements.
1164 */
1165 //================================================================================
1166 bool SMESHGUI_MeshOp::isValid( SUIT_Operation* theOp ) const
1167 {
1168   return SMESHGUI_Operation::isValid( theOp ) && !theOp->inherits( "SMESHGUI_MeshOp" );
1169 }