Salome HOME
reflect algo<->algo and algo->hypos dependencies in GUI
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MeshOp.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/
19 //
20 /**
21 *  SMESH SMESHGUI
22 *
23 *  Copyright (C) 2005  CEA/DEN, EDF R&D
24 *
25 *
26 *
27 *  File   : SMESHGUI_MeshOp.h
28 *  Author : Sergey LITONIN
29 *  Module : SMESHGUI
30 */
31
32 #include "SMESHGUI_MeshOp.h"
33 #include "SMESHGUI_MeshDlg.h"
34 #include "SMESHGUI_ShapeByMeshDlg.h"
35 #include "SMESH_TypeFilter.hxx"
36 #include "SMESHGUI.h"
37
38 #include "SMESHGUI_HypothesesUtils.h"
39 #include "SMESHGUI_Hypotheses.h"
40 #include "SMESHGUI_Utils.h"
41 #include "SMESHGUI_GEOMGenUtils.h"
42 #include "SMESHGUI_VTKUtils.h"
43
44 #include "SMESH_TypeFilter.hxx"
45 #include "SMESH_NumberFilter.hxx"
46
47 #include "GEOM_SelectionFilter.h"
48 #include "GEOMBase.h"
49 #include "GeometryGUI.h"
50
51 #include "SalomeApp_Tools.h"
52 #include "SALOMEDSClient_Study.hxx"
53 #include "SALOMEDSClient_AttributeIOR.hxx"
54 #include "SALOMEDSClient_AttributeName.hxx"
55 #include "SALOMEDS_SComponent.hxx"
56 #include "SALOMEDS_SObject.hxx"
57
58 #include "LightApp_SelectionMgr.h"
59 #include "LightApp_UpdateFlags.h"
60 #include "SUIT_MessageBox.h"
61 #include "SUIT_Desktop.h"
62 #include "SUIT_OverrideCursor.h"
63 #include "SALOME_InteractiveObject.hxx"
64 #include "SALOME_ListIO.hxx"
65
66 #include "utilities.h"
67
68 #include <qstringlist.h>
69 #include <qlineedit.h>
70
71 #include <TopoDS_Shape.hxx>
72 #include <TopExp_Explorer.hxx>
73
74 enum { GLOBAL_ALGO_TAG        =3,
75        GLOBAL_HYPO_TAG        =2,
76        LOCAL_ALGO_TAG         =2,
77        LOCAL_HYPO_TAG         =1,
78        SUBMESH_ON_EDGE_TAG    =5,
79        SUBMESH_ON_WIRE_TAG    =6,
80        SUBMESH_ON_FACE_TAG    =7,
81        SUBMESH_ON_SHELL_TAG   =8,
82        SUBMESH_ON_SOLID_TAG   =9,
83        SUBMESH_ON_COMPOUND_TAG=10 };
84        
85 //================================================================================
86 /*!
87  * \brief Constructor
88   * \param theToCreate - if this parameter is true then operation is used for creation,
89   * for editing otherwise
90  *
91  * Initialize operation
92 */
93 //================================================================================
94 SMESHGUI_MeshOp::SMESHGUI_MeshOp( const bool theToCreate, const bool theIsMesh )
95 : SMESHGUI_SelectionOp(),
96   myToCreate( theToCreate ),
97   myIsMesh( theIsMesh ),
98   myDlg( 0 ),
99   myShapeByMeshOp( 0 )
100 {
101   if ( GeometryGUI::GetGeomGen()->_is_nil() )// check that GEOM_Gen exists
102     GeometryGUI::InitGeomGen();
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( isStudyLocked() )
139     return false;
140
141   QString aMess;
142   if ( !isValid( aMess ) )
143   {
144     dlg()->show();
145     if ( aMess != "" )
146       SUIT_MessageBox::warn1( myDlg,
147         tr( "SMESH_WRN_WARNING" ), aMess, tr( "SMESH_BUT_OK" ) );
148     return false;
149   }
150
151   bool aResult = false;
152   aMess = "";
153   try
154   {
155     if ( myToCreate && myIsMesh )
156       aResult = createMesh( aMess );
157     if ( myToCreate && !myIsMesh )
158       aResult = createSubMesh( aMess );
159     else if ( !myToCreate )
160       aResult = editMeshOrSubMesh( aMess );
161     if ( aResult )
162       update( UF_ObjBrowser | UF_Model );
163   }
164   catch ( const SALOME::SALOME_Exception& S_ex )
165   {
166     SalomeApp_Tools::QtCatchCorbaException( S_ex );
167     aResult = false;
168   }
169   catch ( ... )
170   {
171     aResult = false;
172   }
173
174   if ( aResult )
175   {
176     if ( myToCreate )
177       setDefaultName();
178   }
179   else
180   {
181     if ( aMess == "" )
182       aMess = tr( "SMESH_OPERATION_FAILED" );
183     SUIT_MessageBox::warn1( myDlg,
184       tr( "SMESH_ERROR" ), aMess, tr( "SMESH_BUT_OK" ) );
185   }
186
187   return aResult;
188 }
189
190 //================================================================================
191 /*!
192  * \brief Creates dialog if necessary and shows it
193  *
194  * Virtual method redefined from base class called when operation is started creates
195  * dialog if necessary and shows it, activates selection
196  */
197 //================================================================================
198 void SMESHGUI_MeshOp::startOperation()
199 {
200   if( !myDlg )
201   {
202     myDlg = new SMESHGUI_MeshDlg( myToCreate, myIsMesh );
203     for ( int i = SMESH::DIM_1D; i <= SMESH::DIM_3D; i++ )
204     {
205       connect( myDlg->tab( i ), SIGNAL( createHyp( const int, const int ) ),
206               this, SLOT( onCreateHyp( const int, const int ) ) );
207       connect( myDlg->tab( i ), SIGNAL( editHyp( const int, const int ) ),
208               this, SLOT( onEditHyp( const int, const int ) ) );
209       connect( myDlg->tab( i ), SIGNAL( selectAlgo( const int ) ),
210               this, SLOT( onAlgoSelected( const int ) ) );
211     }
212     connect( myDlg, SIGNAL( hypoSet( const QString& )), SLOT( onHypoSet( const QString& )));
213     connect( myDlg, SIGNAL( geomSelectionByMesh( bool )), SLOT( onGeomSelectionByMesh( bool )));
214
215     if ( myToCreate ) 
216       if ( myIsMesh ) myHelpFileName = "/files/constructing_meshes.htm";
217       else myHelpFileName = "/files/constructing_submeshes.htm";
218     else myHelpFileName = "files/reassigning_hypotheses_and_algorithms.htm";
219   }
220   SMESHGUI_SelectionOp::startOperation();
221
222   // iterate through dimensions and get available algoritms,
223   // set them to the dialog
224   _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
225   for ( int i = SMESH::DIM_1D; i <= SMESH::DIM_3D; i++ )
226   {
227     SMESHGUI_MeshTab* aTab = myDlg->tab( i );
228     QStringList anAvailable;
229     // clear available hypotheses
230     aTab->setAvailableHyps( MainHyp, anAvailable );
231     aTab->setAvailableHyps( AddHyp, anAvailable );
232     // set algos
233     availableHyps( i, Algo, anAvailable, myAvailableHypData[i][Algo] );
234     aTab->setAvailableHyps( Algo, anAvailable );
235   }
236   if ( myToCreate )
237   {
238     setDefaultName();
239     myDlg->activateObject( myIsMesh ? SMESHGUI_MeshDlg::Geom : SMESHGUI_MeshDlg::Mesh );
240   }
241   else
242     myDlg->activateObject( SMESHGUI_MeshDlg::Obj );
243
244   myDlg->setHypoSets( SMESH::GetHypothesesSets() );
245
246   myDlg->setCurrentTab( SMESH::DIM_3D );
247   myDlg->show();
248
249   selectionDone();
250 }
251
252 //================================================================================
253 /*!
254  * \brief Creates selection filter
255   * \param theId - identifier of current selection widget
256   * \retval SUIT_SelectionFilter* - pointer to the created filter or null
257  *
258  * Creates selection filter in accordance with identifier of current selection widget
259  */
260 //================================================================================
261 SUIT_SelectionFilter* SMESHGUI_MeshOp::createFilter( const int theId ) const
262 {
263   if ( theId == SMESHGUI_MeshDlg::Geom )
264   {
265 //     TColStd_MapOfInteger allTypesMap;
266 //     for ( int i = 0; i < 10; i++ )
267 //       allTypesMap.Add( i );
268 //     return new SMESH_NumberFilter( "GEOM", TopAbs_SHAPE, 0, allTypesMap );
269     return new GEOM_SelectionFilter( (SalomeApp_Study*)study(), true );
270   }
271   else if ( theId == SMESHGUI_MeshDlg::Obj && !myToCreate )
272     return new SMESH_TypeFilter( MESHorSUBMESH );
273   else if ( theId == SMESHGUI_MeshDlg::Mesh )
274     return new SMESH_TypeFilter( MESH );
275   else
276     return 0;
277 }
278
279 //================================================================================
280 /*!
281  * \brief check if selected shape is a subshape of the shape to mesh
282   * \retval bool - check result
283  */
284 //================================================================================
285
286 bool SMESHGUI_MeshOp::isSubshapeOk() const
287 {
288   if ( !myToCreate || myIsMesh ) // not submesh creation
289     return false;
290
291   QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
292   QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
293   _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.latin1() );
294   _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
295   if ( pMesh && pGeom ) {
296     SMESH::SMESH_Mesh_var mesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( pMesh );
297     if ( !mesh->_is_nil() ) {
298       GEOM::GEOM_Object_var mainGeom, subGeom;
299       mainGeom = mesh->GetShapeToMesh();
300       subGeom  = SMESH::SObjectToInterface<GEOM::GEOM_Object>( pGeom );
301       if ( !mainGeom->_is_nil() && !subGeom->_is_nil() ) {
302         TopoDS_Shape mainShape, subShape;
303         if ( GEOMBase::GetShape( mainGeom, mainShape ) &&
304              GEOMBase::GetShape( subGeom, subShape ) )
305         {
306           int index = GEOMBase::GetIndex( subShape, mainShape, 0 );
307           if ( index > 0 ) {
308             // 1 is index of mainShape itself
309             return index > 1; // it is a subshape
310           }
311           // is it a group?
312           GEOM::GEOM_Gen_var geomGen = SMESH::GetGEOMGen();
313           _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
314           if ( !geomGen->_is_nil() && aStudy ) {
315             GEOM::GEOM_IGroupOperations_var op =
316               geomGen->GetIGroupOperations( aStudy->StudyId() );
317             if ( ! op->_is_nil() ) {
318               GEOM::GEOM_Object_var mainObj = op->GetMainShape( subGeom );
319               if ( !mainObj->_is_nil() )
320                 return ( string( mainObj->GetEntry() ) == string( mainGeom->GetEntry() ));
321             }
322           }
323         }
324       }
325     }
326   }
327   return false;
328 }
329
330 //================================================================================
331 /*!
332  * \brief find an existing submesh by the selected shape
333   * \retval _PTR(SObject) - the found submesh SObject
334  */
335 //================================================================================
336
337 _PTR(SObject) SMESHGUI_MeshOp::getSubmeshByGeom() const
338 {
339   QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
340   QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
341   _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.latin1() );
342   _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
343   if ( pMesh && pGeom ) {
344     GEOM::GEOM_Object_var geom = SMESH::SObjectToInterface<GEOM::GEOM_Object>( pGeom );
345     if ( !geom->_is_nil() ) {
346       int tag = -1;
347       switch ( geom->GetShapeType() ) {
348       case GEOM::EDGE:     tag = SUBMESH_ON_EDGE_TAG    ; break;
349       case GEOM::WIRE:     tag = SUBMESH_ON_WIRE_TAG    ; break;
350       case GEOM::FACE:     tag = SUBMESH_ON_FACE_TAG    ; break;
351       case GEOM::SHELL:    tag = SUBMESH_ON_SHELL_TAG   ; break;
352       case GEOM::SOLID:    tag = SUBMESH_ON_SOLID_TAG   ; break;
353       case GEOM::COMPOUND: tag = SUBMESH_ON_COMPOUND_TAG; break;
354       default:;
355       }
356       _PTR(SObject) aSubmeshRoot;
357       _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
358       if ( pMesh->FindSubObject( tag, aSubmeshRoot ) )
359       {
360         _PTR(ChildIterator) smIter = aStudy->NewChildIterator( aSubmeshRoot );
361         for (; smIter->More(); smIter->Next() )
362         {
363           _PTR(SObject) aSmObj = smIter->Value();
364           _PTR(ChildIterator) anIter1 = aStudy->NewChildIterator(aSmObj);
365           for (; anIter1->More(); anIter1->Next()) {
366             _PTR(SObject) pGeom2 = anIter1->Value();
367             if ( pGeom2->ReferencedObject( pGeom2 ) &&
368                  pGeom2->GetID() == pGeom->GetID() )
369               return aSmObj;
370           }
371         }
372       }
373     }     
374   }
375   return _PTR(SObject)();
376 }
377
378 //================================================================================
379 /*!
380  * \brief Updates dialog's look and feel
381  *
382  * Virtual method redefined from the base class updates dialog's look and feel
383  */
384 //================================================================================
385 void SMESHGUI_MeshOp::selectionDone()
386 {
387   if ( !dlg()->isShown() )
388     return;
389
390   SMESHGUI_SelectionOp::selectionDone();
391
392   try
393   {
394     // Enable tabs according to shape dimension
395
396     int shapeDim = 3;
397
398     GEOM::GEOM_Object_var aGeomVar;
399     QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
400     _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
401     if ( pGeom ) {
402       aGeomVar = GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
403     }
404     else {
405       QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
406       _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.latin1() );
407       aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj );
408     }
409     if ( !aGeomVar->_is_nil() ) {
410       shapeDim = 0;
411       switch ( aGeomVar->GetShapeType() ) {
412       case GEOM::SOLID:
413       case GEOM::SHELL:  shapeDim = 3; break;
414       case GEOM::FACE:   shapeDim = 2; break;
415       case GEOM::WIRE:   
416       case GEOM::EDGE:   shapeDim = 1; break;
417       case GEOM::VERTEX: shapeDim = 0; break;
418       default:
419         TopoDS_Shape aShape;
420         if ( GEOMBase::GetShape(aGeomVar, aShape)) {
421           TopExp_Explorer exp( aShape, TopAbs_SHELL );
422           if ( exp.More() )
423             shapeDim = 3;
424           else if ( exp.Init( aShape, TopAbs_FACE ), exp.More() )
425             shapeDim = 2;
426           else if ( exp.Init( aShape, TopAbs_EDGE ), exp.More() )
427             shapeDim = 1;
428           else
429             shapeDim = 0;
430         }
431       }
432     }
433     myDlg->setMaxHypoDim( shapeDim );
434
435     if ( !myToCreate ) // edition: read hypotheses
436     {
437       QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
438       _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.latin1() );
439       if ( pObj != 0 )
440       {
441         SMESH::SMESH_subMesh_var aVar =
442           SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() );
443         myDlg->setObjectShown( SMESHGUI_MeshDlg::Mesh, !aVar->_is_nil() );
444         myDlg->objectWg( SMESHGUI_MeshDlg::Mesh, SMESHGUI_MeshDlg::Btn )->hide();
445         myDlg->updateGeometry();
446         myDlg->adjustSize();
447         readMesh();
448       }
449       else
450         myDlg->reset();
451
452     }
453     else if ( !myIsMesh ) // submesh creation
454     {
455       // if a submesh on the selected shape already exist, pass to submesh edition mode
456       if ( _PTR(SObject) pSubmesh = getSubmeshByGeom() ) {
457         SMESH::SMESH_subMesh_var sm = 
458           SMESH::SObjectToInterface<SMESH::SMESH_subMesh>( pSubmesh );
459         bool editSubmesh = ( !sm->_is_nil() &&
460                              SUIT_MessageBox::question2( myDlg, tr( "SMESH_WARNING" ),
461                                                          tr( "EDIT_SUBMESH_QUESTION"),
462                                                          tr( "SMESH_BUT_YES" ),
463                                                          tr( "SMESH_BUT_NO" ), 1, 0, 0 ));
464         if ( editSubmesh )
465         {
466           selectionMgr()->clearFilters();
467           selectObject( pSubmesh );
468           SMESHGUI::GetSMESHGUI()->switchToOperation(704);
469           return;
470         }
471         else
472         {
473           selectObject( _PTR(SObject)() );
474           myDlg->selectObject( "", SMESHGUI_MeshDlg::Geom, "" );
475         }
476       }
477
478       // enable/disable popup for choice of geom selection way
479       bool enable = false;
480       QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
481       if ( _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.latin1() )) {
482         SMESH::SMESH_Mesh_var mesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( pMesh );
483         if ( !mesh->_is_nil() )
484           enable = ( shapeDim > 1 ) && ( mesh->NbEdges() > 0 );
485       }
486       myDlg->setGeomPopupEnabled( enable );
487     }
488   }
489   catch ( const SALOME::SALOME_Exception& S_ex )
490   {
491     SalomeApp_Tools::QtCatchCorbaException( S_ex );
492   }
493   catch ( ... )
494   {
495   }
496 }
497
498 //================================================================================
499 /*!
500  * \brief Verifies validity of input data
501   * \param theMess - Output parameter intended for returning error message
502   * \retval bool  - TRUE if input data is valid, false otherwise
503  *
504  * Verifies validity of input data. This method is called when "Apply" or "OK" button
505  * is pressed before mesh creation or editing.
506  */
507 //================================================================================
508 bool SMESHGUI_MeshOp::isValid( QString& theMess ) const
509 {
510   // Selected object to be  edited
511   if ( !myToCreate && myDlg->selectedObject( SMESHGUI_MeshDlg::Obj ) == "" )
512   {
513     theMess = tr( "THERE_IS_NO_OBJECT_FOR_EDITING" );
514     return false;
515   }
516
517   // Name
518   QString aMeshName = myDlg->objectText( SMESHGUI_MeshDlg::Obj );
519   aMeshName = aMeshName.stripWhiteSpace();
520   if ( aMeshName == "" )
521   {
522     theMess = myIsMesh ? tr( "NAME_OF_MESH_IS_EMPTY" ) : tr( "NAME_OF_SUBMESH_IS_EMPTY" );
523     return false;
524   }
525
526   // Imported mesh, if create sub-mesh or edit mesh
527   if ( !myToCreate || ( myToCreate && !myIsMesh ))
528   {
529     QString aMeshEntry = myDlg->selectedObject
530       ( myToCreate ? SMESHGUI_MeshDlg::Mesh : SMESHGUI_MeshDlg::Obj );
531     if ( _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.latin1() )) {
532       SMESH::SMESH_Mesh_var mesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( pMesh );
533       if ( !mesh->_is_nil() && CORBA::is_nil( mesh->GetShapeToMesh() )) {
534         theMess = tr( "IMPORTED_MESH" );
535         return false;
536       }
537     }
538   }
539
540   // Geom
541   if ( myToCreate )
542   {
543     QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
544     if ( aGeomEntry == "" )
545     {
546       theMess = tr( "GEOMETRY_OBJECT_IS_NOT_DEFINED" );
547       return false;
548     }
549     _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
550     if ( !pGeom || GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() )->_is_nil() )
551     {
552       theMess = tr( "GEOMETRY_OBJECT_IS_NULL" );
553       return false;
554     }
555
556     // Mesh
557     if ( !myIsMesh ) // i.e sub-mesh creation,
558     {
559       QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
560       if ( aMeshEntry == "" )
561       {
562         theMess = tr( "MESH_IS_NOT_DEFINED" );
563         return false;
564       }
565       _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.latin1() );
566       if ( !pMesh || SMESH::SMESH_Mesh::_narrow( _CAST( SObject,pMesh )->GetObject() )->_is_nil() )
567       {
568         theMess = tr( "MESH_IS_NULL" );
569         return false;
570       }
571       if ( !isSubshapeOk() )
572       {
573         theMess = tr( "INVALID_SUBSHAPE" );
574         return false;
575       }
576     }
577   }
578     
579   return true;
580 }
581
582 //================================================================================
583 /*!
584  * \brief check compatibility of the algorithm and another algorithm or hypothesis
585   * \param theAlgoData - algorithm data
586   * \param theHypData - hypothesis data
587   * \param theHypType - hypothesis type
588   * \param theHypTypeName - hypothesis type name, must be provided if 2-nd arg is not algo
589   * \retval bool - check result
590  */
591 //================================================================================
592
593 static bool isCompatible(const HypothesisData* theAlgoData,
594                          const HypothesisData* theHypData,
595                          const int             theHypType)
596 {
597   if ( !theAlgoData )
598     return true;
599
600   if ( theHypType == SMESHGUI_MeshOp::Algo )
601     return SMESH::IsCompatibleAlgorithm( theAlgoData, theHypData );
602
603   bool isAux;
604   return ( SMESH::IsAvailableHypothesis( theAlgoData, theHypData->TypeName, isAux ));
605 }
606
607 //================================================================================
608 /*!
609  * \brief Gets available hypotheses or algorithms
610   * \param theDim - specifies dimension of returned hypotheses/algorifms
611   * \param theHypType - specifies whether algorims or hypotheses or additional ones
612   * are retrieved (possible values are in HypType enumeration)
613   * \param theHyps - Output list of hypotheses' names
614   * \param theAlgoData - to select hypos able to be used by this algo (optional)
615  *
616  * Gets available hypotheses or algorithm in accordance with input parameters
617  */
618 //================================================================================
619 void SMESHGUI_MeshOp::availableHyps( const int       theDim,
620                                      const int       theHypType,
621                                      QStringList&    theHyps,
622                                      THypDataList&   theDataList,
623                                      HypothesisData* theAlgoData ) const
624 {
625   theDataList.clear();
626   theHyps.clear();
627   bool isAlgo = ( theHypType == Algo );
628   bool isAux  = ( theHypType == AddHyp );
629   QStringList aHypTypeNameList = SMESH::GetAvailableHypotheses( isAlgo, theDim, isAux );
630
631   QStringList::const_iterator anIter;
632   for ( anIter = aHypTypeNameList.begin(); anIter != aHypTypeNameList.end(); ++anIter )
633   {
634     HypothesisData* aData = SMESH::GetHypothesisData( *anIter );
635     if ( isCompatible ( theAlgoData, aData, theHypType )) {
636       theDataList.append( aData );
637       theHyps.append( aData->Label );
638     }
639   }
640 }
641
642 //================================================================================
643 /*!
644  * \brief Gets existing hypotheses or algorithms
645   * \param theDim - specifies dimension of returned hypotheses/algorifms
646   * \param theHypType - specifies whether algorims or hypotheses or additional ones
647   * are retrieved (possible values are in HypType enumeration)
648   * \param theFather - start object for finding ( may be component, mesh, or sub-mesh )
649   * \param theDataList - output list of hypotheses data
650   * \param theHyps - output list of names.
651   * \param theHypVars - output list of variables.
652   * \param theAlgoData - to select hypos able to be used by this algo (optional)
653  *
654  * Gets existing (i.e. already created) hypotheses or algorithm in accordance with
655  * input parameters
656  */
657 //================================================================================
658 void SMESHGUI_MeshOp::existingHyps( const int theDim,
659                                     const int theHypType,
660                                     _PTR(SObject) theFather,
661                                     QStringList& theHyps,
662                                     QValueList<SMESH::SMESH_Hypothesis_var>& theHypVars,
663                                     HypothesisData* theAlgoData)
664 {
665   // Clear hypoheses list
666   theHyps.clear();
667   theHypVars.clear();
668
669   if ( !theFather )
670     return;
671
672   const bool isAux  = ( theHypType == AddHyp );
673
674   _PTR(SObject)          aHypRoot;
675   _PTR(GenericAttribute) anAttr;
676   _PTR(AttributeName)    aName;
677   _PTR(AttributeIOR)     anIOR;
678
679   bool isMesh = !_CAST( SComponent, theFather );
680   int aPart = -1;
681   if ( isMesh )
682     aPart = theHypType == Algo ? GLOBAL_ALGO_TAG : GLOBAL_HYPO_TAG;
683   else
684     aPart = theHypType == Algo ? LOCAL_ALGO_TAG : LOCAL_HYPO_TAG;
685
686   if ( theFather->FindSubObject( aPart, aHypRoot ) )
687   {
688     _PTR(ChildIterator) anIter =
689       SMESH::GetActiveStudyDocument()->NewChildIterator( aHypRoot );
690     for (; anIter->More(); anIter->Next() )
691     {
692       _PTR(SObject) anObj = anIter->Value();
693       if ( isMesh ) // i.e. mesh or submesh
694       {
695         _PTR(SObject) aRefObj;
696         if ( anObj->ReferencedObject( aRefObj ) )
697           anObj = aRefObj;
698         else
699           continue;
700       }
701       if ( anObj->FindAttribute( anAttr, "AttributeName" ) )
702       {
703         aName = anAttr;
704         CORBA::Object_var aVar = _CAST(SObject,anObj)->GetObject();
705         if ( !CORBA::is_nil( aVar ) )
706         {
707           SMESH::SMESH_Hypothesis_var aHypVar = SMESH::SMESH_Hypothesis::_narrow( aVar );
708           if ( !aHypVar->_is_nil() )
709           {
710             QString aHypType( aHypVar->GetName() );
711             HypothesisData* aData = SMESH::GetHypothesisData( aHypType );
712             if ( ( theDim == -1 || aData->Dim.contains( theDim ) ) &&
713                  ( isCompatible ( theAlgoData, aData, theHypType )) &&
714                  ( isAux == aData->IsAux ))
715             {
716               //theDataList.append( aData );
717               theHyps.append( aName->Value().c_str() );
718               theHypVars.append( aHypVar );
719             }
720           }
721         }
722       }
723     }
724   }
725 }
726
727 //================================================================================
728 /*!
729  * \brief If create or edit a submesh, return a hypothesis holding parameters used
730  *        to mesh a subshape
731   * \param aHypType - The hypothesis type name
732   * \param aServerLib - Server library name
733   * \param hypData - The structure holding the hypothesis type etc.
734   * \retval SMESH::SMESH_Hypothesis_var - the hypothesis holding parameter values
735  */
736 //================================================================================
737
738 SMESH::SMESH_Hypothesis_var
739 SMESHGUI_MeshOp::getInitParamsHypothesis( const QString& aHypType,
740                                           const QString& aServerLib ) const
741 {
742   if ( aHypType.isEmpty() || aServerLib.isEmpty() )
743     return SMESH::SMESH_Hypothesis::_nil();
744
745   const int nbColonsInMeshEntry = 3;
746   bool isSubMesh = myToCreate ?
747     !myIsMesh :
748     myDlg->selectedObject( SMESHGUI_MeshDlg::Obj ).contains(':') > nbColonsInMeshEntry; 
749
750   if ( isSubMesh )
751   {
752     // get mesh and geom object
753     SMESH::SMESH_Mesh_var aMeshVar = SMESH::SMESH_Mesh::_nil();
754     GEOM::GEOM_Object_var aGeomVar = GEOM::GEOM_Object::_nil();
755
756     QString anEntry = myDlg->selectedObject
757       ( myToCreate ? SMESHGUI_MeshDlg::Mesh : SMESHGUI_MeshDlg::Obj );
758     if ( _PTR(SObject) pObj = studyDS()->FindObjectID( anEntry.latin1() ))
759     {
760       CORBA::Object_ptr Obj = _CAST( SObject,pObj )->GetObject();
761       if ( myToCreate ) // mesh and geom may be selected
762       {
763         aMeshVar = SMESH::SMESH_Mesh::_narrow( Obj );
764         anEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
765         if ( _PTR(SObject) pGeom = studyDS()->FindObjectID( anEntry.latin1() ))
766           aGeomVar= GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
767       }
768       else // edition: sub-mesh may be selected
769       {
770         SMESH::SMESH_subMesh_var sm = SMESH::SMESH_subMesh::_narrow( Obj );
771         if ( !sm->_is_nil() ) {
772           aMeshVar = sm->GetFather();
773           aGeomVar = sm->GetSubShape();
774         }
775       }
776     }
777
778     if ( !aMeshVar->_is_nil() && !aGeomVar->_is_nil() )
779       return SMESHGUI::GetSMESHGen()->GetHypothesisParameterValues( aHypType,
780                                                                     aServerLib,
781                                                                     aMeshVar,
782                                                                     aGeomVar );
783   }
784   return SMESH::SMESH_Hypothesis::_nil();
785 }
786
787 //================================================================================
788 /*!
789  * \Brief Returns tab dimention  
790   * \param tab - the tab in the dlg
791   * \param dlg - my dialogue
792   * \retval int - dimention
793  */
794 //================================================================================
795
796 static int getTabDim (const QObject* tab, SMESHGUI_MeshDlg* dlg )
797 {
798   int aDim = -1;
799   for (int i = SMESH::DIM_1D; i <= SMESH::DIM_3D; i++)
800     if (tab == dlg->tab(i))
801       aDim = i;
802   return aDim;
803 }
804
805 //================================================================================
806 /*!
807  * \brief Create hypothesis
808   * \param theHypType - hypothesis category (main or additional)
809   * \param theIndex - index of type of hypothesis to be cerated
810  *
811  * Specifies dimension of hypothesis to be created (using sender() method),
812  * specifies its type and calls method for hypothesis creation
813  */
814 //================================================================================
815 void SMESHGUI_MeshOp::onCreateHyp( const int theHypType, const int theIndex )
816 {
817   // Specifies dimension of hypothesis to be created
818   int aDim = getTabDim( sender(), myDlg );
819   if (aDim == -1)
820     return;
821
822   // Specifies type of hypothesis to be created
823   THypDataList& dataList = myAvailableHypData[ aDim ][ theHypType ];
824   if (theIndex < 0 || theIndex >= dataList.count())
825     return;
826   QString aHypTypeName = dataList[ theIndex ]->TypeName;
827
828   // Create hypothesis
829   createHypothesis(aDim, theHypType, aHypTypeName);
830 }
831
832 //================================================================================
833 /*!
834  *  Create hypothesis and update dialog.
835  *  \param theDim - dimension of hypothesis to be created
836  *  \param theType - hypothesis category (algorithm, hypothesis, additional hypothesis)
837  *  \param theTypeName - specifies hypothesis to be created
838  */
839 //================================================================================
840 void SMESHGUI_MeshOp::createHypothesis (const int theDim,
841                                         const int theType,
842                                         const QString& theTypeName)
843 {
844   HypothesisData* aData = SMESH::GetHypothesisData(theTypeName.latin1());
845   if (!aData)
846     return;
847
848   // existing hypos
849   int nbHyp = myExistingHyps[theDim][theType].count();
850
851   QString aClientLibName = aData->ClientLibName;
852   if (aClientLibName == "") {
853     // Call hypothesis creation server method (without GUI)
854     SMESH::CreateHypothesis(theTypeName, aData->Label, false);
855   } else {
856     // Get hypotheses creator client (GUI)
857     SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator(theTypeName);
858
859     // Create hypothesis
860     if (aCreator) {
861       // When create or edit a submesh, try to initialize a new hypothesis
862       // with values used to mesh a subshape
863       SMESH::SMESH_Hypothesis_var initParamHyp =
864         getInitParamsHypothesis(theTypeName, aData->ServerLibName);
865       aCreator->create(initParamHyp, myDlg);
866     } else {
867       SMESH::CreateHypothesis(theTypeName, aData->Label, false);
868     }
869   }
870
871   _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent("SMESH");
872
873   HypothesisData* algoData = hypData( theDim, Algo, currentHyp( theDim, Algo ));
874   QStringList aNewHyps;
875   existingHyps(theDim, theType, aFather, aNewHyps, myExistingHyps[theDim][theType], algoData);
876   if (aNewHyps.count() > nbHyp) {
877     for (int i = nbHyp; i < aNewHyps.count(); i++)
878       myDlg->tab(theDim)->addHyp(theType, aNewHyps[i]);
879   }
880 }
881
882 //================================================================================
883 /*!
884  * \brief Calls plugin methods for hypothesis editing
885   * \param theHypType - specifies whether main hypothesis or additional one
886   * is edited
887   * \param theIndex - index of existing hypothesis
888  *
889  * Calls plugin methods for hypothesis editing
890  */
891 //================================================================================
892 void SMESHGUI_MeshOp::onEditHyp( const int theHypType, const int theIndex )
893 {
894   // Speicfies dimension of hypothesis to be created
895   int aDim = getTabDim( sender(), myDlg );
896   if (aDim == -1)
897     return;
898
899   QValueList<SMESH::SMESH_Hypothesis_var> aList = myExistingHyps[ aDim ][ theHypType ];
900   if ( theIndex < 0 || theIndex >= aList.count() )
901     return;
902   SMESH::SMESH_Hypothesis_var aHyp = aList[ theIndex - 1 ];
903   if ( aHyp->_is_nil() )
904     return;
905
906   char* aTypeName = aHyp->GetName();
907   SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator( aTypeName );
908   if ( aCreator )
909     aCreator->edit( aHyp.in(), dlg() );
910 }
911
912 //================================================================================
913 /*!
914  * \brief access to hypothesis data 
915   * \param theDim - hyp dimension
916   * \param theHypType - hyp type (Algo,MainHyp or AddHyp)
917   * \param theIndex - index in the list
918   * \retval HypothesisData* - result data, may be 0
919  */
920 //================================================================================
921
922 HypothesisData* SMESHGUI_MeshOp::hypData( const int theDim,
923                                           const int theHypType,
924                                           const int theIndex)
925 {
926   if ( theDim     > -1 && theDim     < 3 &&
927        theHypType > -1 && theHypType < NbHypTypes &&
928        theIndex   > -1 && theIndex   < myAvailableHypData[ theDim ][ theHypType ].count() )
929     return myAvailableHypData[ theDim ][ theHypType ][ theIndex ];
930   return 0;
931 }
932
933 //================================================================================
934 /*!
935  * \brief Set available algos and hypos according to the selected algorithm
936   * \param theIndex - algorithm index
937  */
938 //================================================================================
939
940 void SMESHGUI_MeshOp::onAlgoSelected( const int theIndex,
941                                       const int theDim )
942 {
943   if ( myIgnoreAlgoSelection )
944     return;
945
946   int aDim = theDim < 0 ? getTabDim( sender(), myDlg ): theDim;
947   if (aDim == -1)
948     return;
949
950   // find highest available dimension, all algos of this dimension are available for choice
951   int aTopDim = -1;
952   for (int i = SMESH::DIM_1D; i <= SMESH::DIM_3D; i++)
953     if (isAccessibleDim( i ))
954       aTopDim = i;
955   if (aTopDim == -1)
956     return;
957
958   HypothesisData* algoData = hypData( aDim, Algo, theIndex );
959   HypothesisData* algoByDim[3];
960   algoByDim[ aDim ] = algoData;
961
962   QStringList anAvailable;
963   if ( !algoData ) { // all algos becomes available
964     availableHyps( aDim, Algo, anAvailable, myAvailableHypData[ aDim ][ Algo ]);
965     myDlg->tab( aDim )->setAvailableHyps( Algo, anAvailable );
966   }
967
968   // check that algorithms of other dimentions are compatible with
969   // the selected one
970
971    // 2 loops: backward and forward from algo dimension
972   for ( int forward = false; forward <= true; ++forward )
973   {
974     int dim = aDim + 1, lastDim = SMESH::DIM_3D, dir = 1;
975     if ( !forward ) {
976       dim = aDim - 1; lastDim = SMESH::DIM_1D; dir = -1;
977     }
978     HypothesisData* prevAlgo = algoData;
979     for ( ; dim * dir <= lastDim * dir ; dim += dir )
980     {
981       if ( !isAccessibleDim( dim ))
982         continue;
983       // get currently selected algo
984       int algoIndex = currentHyp( dim, Algo );
985       HypothesisData* curAlgo = hypData( dim, Algo, algoIndex );
986       if ( curAlgo ) { // some algo selected
987         if ( !isCompatible( prevAlgo, curAlgo, Algo ))
988           curAlgo = 0;
989       }
990       // set new available algoritms
991       availableHyps( dim, Algo, anAvailable, myAvailableHypData[dim][Algo], prevAlgo );
992       HypothesisData* soleCompatible = 0;
993       if ( anAvailable.count() == 1 )
994         soleCompatible = myAvailableHypData[dim][Algo][0];
995       if ( dim == aTopDim && prevAlgo ) // all available algoritms should be selectable any way
996         availableHyps( dim, Algo, anAvailable, myAvailableHypData[dim][Algo], 0 );
997       myDlg->tab( dim )->setAvailableHyps( Algo, anAvailable );
998
999       // restore previously selected algo
1000       algoIndex = myAvailableHypData[dim][Algo].findIndex( curAlgo );
1001       if ( algoIndex < 0 && soleCompatible )
1002         // select the sole compatible algo
1003         algoIndex = myAvailableHypData[dim][Algo].findIndex( soleCompatible );
1004       setCurrentHyp( dim, Algo, algoIndex );
1005
1006       // remember current algo
1007       prevAlgo = algoByDim[ dim ] = hypData( dim, Algo, algoIndex );
1008     }
1009   }
1010
1011   // set hypotheses corresponding to the found algoritms
1012
1013   QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
1014   _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.latin1() );
1015   if ( !pObj )
1016     pObj = SMESH::GetActiveStudyDocument()->FindComponent("SMESH");
1017
1018   for ( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ )
1019   {
1020     if ( !isAccessibleDim( dim ))
1021       continue;
1022     for ( int type = MainHyp; type < NbHypTypes; type++ )
1023     {
1024       myAvailableHypData[ dim ][ type ].clear();
1025       QStringList anAvailable, anExisting;
1026       SMESH::SMESH_Hypothesis_var curHyp;
1027
1028       // get hyps compatible with curAlgo
1029       if ( HypothesisData* curAlgo = algoByDim[ dim ] )
1030       {
1031         // get current existing hypothesis
1032         int hypIndex = currentHyp( dim, type );
1033         if ( hypIndex >= 0 && hypIndex < myExistingHyps[ dim ][ type ].count() ) {
1034           curHyp = myExistingHyps[ dim ][ type ][ hypIndex ];
1035           QString hypTypeName = curHyp->GetName();
1036           HypothesisData* hypData = SMESH::GetHypothesisData( hypTypeName );
1037           if ( !isCompatible( curAlgo, hypData, type ))
1038             curHyp = SMESH::SMESH_Hypothesis::_nil();
1039         }
1040         existingHyps( dim, type, pObj, anExisting, myExistingHyps[ dim ][ type ], curAlgo);
1041         availableHyps( dim, type, anAvailable, myAvailableHypData[ dim ][ type ], curAlgo);
1042       }
1043       // set list of hypotheses
1044       myDlg->tab( dim )->setAvailableHyps( type, anAvailable );
1045       myDlg->tab( dim )->setExistingHyps( type, anExisting );
1046
1047       // set current hypothesis
1048       int hypIndex = -1;
1049       if ( !curHyp->_is_nil() && !anExisting.isEmpty() )
1050         hypIndex = this->find( curHyp, myExistingHyps[ dim ][ type ]);
1051       setCurrentHyp( dim, type, hypIndex );
1052     }
1053   }
1054 }
1055
1056 //================================================================================
1057 /*!
1058  * \brief Creates and selects hypothesis of hypotheses set 
1059   * \param theSetName - The name of hypotheses set
1060  */
1061 //================================================================================
1062 void SMESHGUI_MeshOp::onHypoSet( const QString& theSetName )
1063 {
1064   HypothesesSet* aHypoSet = SMESH::GetHypothesesSet(theSetName);
1065   if (!aHypoSet) return;
1066
1067   for (int aHypType = Algo; aHypType < AddHyp; aHypType++) {
1068     bool isAlgo = (aHypType == Algo);
1069
1070     // clear all hyps
1071     for (int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++)
1072       setCurrentHyp(dim, aHypType, -1);
1073
1074     // set hyps from the set
1075     QStringList* aHypoList = isAlgo ? &aHypoSet->AlgoList : &aHypoSet->HypoList;
1076     for (int i = 0, n = aHypoList->count(); i < n; i++) {
1077       const QString& aHypoTypeName = (*aHypoList)[ i ];
1078       HypothesisData* aHypData = SMESH::GetHypothesisData(aHypoTypeName);
1079       if (!aHypData)
1080         continue;
1081
1082       int aDim = aHypData->Dim[0];
1083       // create or/and set
1084       if (isAlgo) {
1085         QStringList tmp;
1086         availableHyps( aDim, Algo, tmp, myAvailableHypData[aDim][Algo] );
1087         int index = myAvailableHypData[aDim][Algo].findIndex( aHypData );
1088         setCurrentHyp( aDim, Algo, index );
1089         onAlgoSelected( index, aDim );
1090       }
1091       else {
1092         bool mainHyp = true;
1093         int index = myAvailableHypData[aDim][MainHyp].findIndex( aHypData );
1094         if ( index < 0 ) {
1095           mainHyp = false;
1096           index = myAvailableHypData[aDim][AddHyp].findIndex( aHypData );
1097         }
1098         if (index >= 0)
1099           createHypothesis(aDim, mainHyp ? MainHyp : AddHyp, aHypoTypeName);
1100       }
1101     } // loop on hypos in the set
1102   } // loop on algo/hypo
1103 }
1104
1105 //================================================================================
1106 /*!
1107  * \brief Creates mesh
1108   * \param theMess - Output parameter intended for returning error message
1109   * \retval bool  - TRUE if mesh is created, FALSE otherwise
1110  *
1111  * Creates mesh
1112  */
1113 //================================================================================
1114 bool SMESHGUI_MeshOp::createMesh( QString& theMess )
1115 {
1116   theMess = "";
1117
1118   QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
1119   _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
1120   GEOM::GEOM_Object_var aGeomVar =
1121     GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
1122
1123   SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen();
1124   if ( aSMESHGen->_is_nil() )
1125     return false;
1126
1127   SUIT_OverrideCursor aWaitCursor;
1128
1129   // create mesh
1130   SMESH::SMESH_Mesh_var aMeshVar = aSMESHGen->CreateMesh( aGeomVar );
1131   if ( aMeshVar->_is_nil() )
1132     return false;
1133   _PTR(SObject) aMeshSO = SMESH::FindSObject( aMeshVar.in() );
1134   if ( aMeshSO )
1135     SMESH::SetName( aMeshSO, myDlg->objectText( SMESHGUI_MeshDlg::Obj ).latin1() );
1136
1137   for ( int aDim = SMESH::DIM_1D; aDim <= SMESH::DIM_3D; aDim++ )
1138   {
1139     if ( !isAccessibleDim( aDim )) continue;
1140
1141     // assign hypotheses
1142     for ( int aHypType = MainHyp; aHypType <= AddHyp; aHypType++ )
1143     {
1144       int aHypIndex = currentHyp( aDim, aHypType );
1145       if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() )
1146       {
1147         SMESH::SMESH_Hypothesis_var aHypVar = myExistingHyps[ aDim ][ aHypType ][ aHypIndex ];
1148         if ( !aHypVar->_is_nil() )
1149           SMESH::AddHypothesisOnMesh( aMeshVar, aHypVar );
1150       }
1151     }
1152     // find or create algorithm
1153     SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( aDim );
1154     if ( !anAlgoVar->_is_nil() )
1155       SMESH::AddHypothesisOnMesh( aMeshVar, anAlgoVar );
1156   }
1157   return true;
1158 }
1159
1160 //================================================================================
1161 /*!
1162  * \brief Creates sub-mesh
1163   * \param theMess - Output parameter intended for returning error message
1164   * \retval bool  - TRUE if sub-mesh is created, FALSE otherwise
1165  *
1166  * Creates sub-mesh
1167  */
1168 //================================================================================
1169 bool SMESHGUI_MeshOp::createSubMesh( QString& theMess )
1170 {
1171   theMess = "";
1172
1173   SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen();
1174   if ( aSMESHGen->_is_nil() )
1175     return false;
1176
1177   // get mesh object
1178   QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
1179   _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.latin1() );
1180   SMESH::SMESH_Mesh_var aMeshVar =
1181     SMESH::SMESH_Mesh::_narrow( _CAST( SObject,pMesh )->GetObject() );
1182
1183   // get geom object
1184   QString aGeomEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Geom );
1185   _PTR(SObject) pGeom = studyDS()->FindObjectID( aGeomEntry.latin1() );
1186   GEOM::GEOM_Object_var aGeomVar =
1187     GEOM::GEOM_Object::_narrow( _CAST( SObject,pGeom )->GetObject() );
1188
1189   SUIT_OverrideCursor aWaitCursor;
1190
1191   // create sub-mesh
1192   QString aName = myDlg->objectText( SMESHGUI_MeshDlg::Obj );
1193   SMESH::SMESH_subMesh_var aSubMeshVar = aMeshVar->GetSubMesh( aGeomVar, aName.latin1() );
1194
1195   for ( int aDim = SMESH::DIM_1D; aDim <= SMESH::DIM_3D; aDim++ )
1196   {
1197     if ( !isAccessibleDim( aDim )) continue;
1198
1199     // find or create algorithm
1200     SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( aDim );
1201     if ( !anAlgoVar->_is_nil() )
1202       SMESH::AddHypothesisOnSubMesh( aSubMeshVar, anAlgoVar );
1203     // assign hypotheses
1204     for ( int aHypType = MainHyp; aHypType <= AddHyp; aHypType++ )
1205     {
1206       int aHypIndex = currentHyp( aDim, aHypType );
1207       if ( aHypIndex >= 0 && aHypIndex < myExistingHyps[ aDim ][ aHypType ].count() )
1208       {
1209         SMESH::SMESH_Hypothesis_var aHypVar =
1210           myExistingHyps[ aDim ][ aHypType ][ aHypIndex ];
1211         if ( !aHypVar->_is_nil() )
1212           SMESH::AddHypothesisOnSubMesh( aSubMeshVar, aHypVar );
1213       }
1214     }
1215   }
1216   return true;
1217 }
1218
1219 //================================================================================
1220 /*!
1221  * \brief Gets current hypothesis or algorithms
1222   * \param theDim - dimension of hypothesis or algorithm
1223   * \param theHypType - Type of hypothesis (Algo, MainHyp, AddHyp)
1224   * \retval int - current hypothesis or algorithms
1225  *
1226  * Gets current hypothesis or algorithms
1227  */
1228 //================================================================================
1229 int SMESHGUI_MeshOp::currentHyp( const int theDim, const int theHypType ) const
1230 {
1231   return myDlg->tab( theDim )->currentHyp( theHypType ) - 1;
1232 }
1233
1234 //================================================================================
1235 /*!
1236  * \brief Returns true if hypotheses of given dim can be assigned
1237   * \param theDim - hypotheses dimension
1238   * \retval bool - result
1239  */
1240 //================================================================================
1241 bool SMESHGUI_MeshOp::isAccessibleDim( const int theDim ) const
1242 {
1243   return myDlg->tab( theDim )->isEnabled();
1244 }
1245
1246 //================================================================================
1247 /*!
1248  * \brief Sets current hypothesis or algorithms
1249   * \param theDim - dimension of hypothesis or algorithm
1250   * \param theHypType - Type of hypothesis (Algo, MainHyp, AddHyp)
1251   * \param theIndex - Index of hypothesis
1252  *
1253  * Gets current hypothesis or algorithms
1254  */
1255 //================================================================================
1256 void SMESHGUI_MeshOp::setCurrentHyp( const int theDim,
1257                                      const int theHypType,
1258                                      const int theIndex )
1259 {
1260   myIgnoreAlgoSelection = true;
1261   myDlg->tab( theDim )->setCurrentHyp( theHypType, theIndex + 1 );
1262   myIgnoreAlgoSelection = false;
1263 }
1264
1265 //================================================================================
1266 /*!
1267  * \brief Generates default and sets mesh/submesh name
1268  *
1269  * Generates and sets default mesh/submesh name(Mesh_1, Mesh_2, etc.)
1270  */
1271 //================================================================================
1272 void SMESHGUI_MeshOp::setDefaultName() const
1273 {
1274   QString aResName;
1275
1276   _PTR(Study) aStudy = SMESH::GetActiveStudyDocument();
1277   int i = 1;
1278   QString aPrefix = tr( myIsMesh ? "SMESH_OBJECT_MESH" : "SMESH_SUBMESH" ) + "_";
1279   _PTR(SObject) anObj;
1280   do
1281   {
1282     aResName = aPrefix + QString::number( i++ );
1283     anObj = aStudy->FindObject( aResName.latin1() );
1284   }
1285   while ( anObj );
1286
1287   QLineEdit* aControl = ( QLineEdit* )myDlg->objectWg(
1288     SMESHGUI_MeshDlg::Obj, SMESHGUI_MeshDlg::Control );
1289   aControl->setText( aResName );
1290 }
1291
1292 //================================================================================
1293 /*!
1294  * \brief Gets algorithm or creates it if necessary
1295   * \param theDim - specifies dimension of returned hypotheses/algorifms
1296   * \retval SMESH::SMESH_Hypothesis_var - algorithm
1297  *
1298  * Gets algorithm or creates it if necessary
1299  */
1300 //================================================================================
1301 SMESH::SMESH_Hypothesis_var SMESHGUI_MeshOp::getAlgo( const int theDim )
1302 {
1303   SMESH::SMESH_Hypothesis_var anAlgoVar;
1304
1305   // get type of the selected algo
1306   int aHypIndex = currentHyp( theDim, Algo );
1307   THypDataList& dataList = myAvailableHypData[ theDim ][ Algo ];
1308   if ( aHypIndex < 0 || aHypIndex >= dataList.count())
1309     return anAlgoVar;
1310   QString aHypName = dataList[ aHypIndex ]->TypeName;
1311
1312   // get existing algoritms
1313   _PTR(SObject) pObj = SMESH::GetActiveStudyDocument()->FindComponent("SMESH");
1314   QStringList tmp;
1315   existingHyps( theDim, Algo, pObj, tmp, myExistingHyps[ theDim ][ Algo ]);
1316
1317   // look for anexisting algo of such a type
1318   QValueList<SMESH::SMESH_Hypothesis_var>& aHypVarList = myExistingHyps[ theDim ][ Algo ];
1319   QValueList<SMESH::SMESH_Hypothesis_var>::iterator anIter;
1320   for ( anIter = aHypVarList.begin(); anIter != aHypVarList.end(); anIter++ )
1321   {
1322     SMESH::SMESH_Hypothesis_var aHypVar = *anIter;
1323     if ( !aHypVar->_is_nil() && aHypName == aHypVar->GetName() )
1324     {
1325       anAlgoVar = aHypVar;
1326       break;
1327     }
1328   }
1329
1330   if (anAlgoVar->_is_nil()) {
1331     HypothesisData* aHypData = SMESH::GetHypothesisData( aHypName );
1332     if (aHypData) {
1333       QString aClientLibName = aHypData->ClientLibName;
1334       if (aClientLibName == "") {
1335         // Call hypothesis creation server method (without GUI)
1336         SMESH::CreateHypothesis(aHypName, aHypData->Label, true);
1337       } else {
1338         // Get hypotheses creator client (GUI)
1339         SMESHGUI_GenericHypothesisCreator* aCreator = SMESH::GetHypothesisCreator(aHypName);
1340
1341         // Create algorithm
1342         if (aCreator)
1343           aCreator->create(true, myDlg);
1344         else
1345           SMESH::CreateHypothesis(aHypName, aHypData->Label, true);
1346       }
1347       QStringList tmpList;
1348       _PTR(SComponent) aFather = SMESH::GetActiveStudyDocument()->FindComponent( "SMESH" );
1349       existingHyps( theDim, Algo, aFather, tmpList, myExistingHyps[ theDim ][ Algo ] );
1350     }
1351
1352     QValueList<SMESH::SMESH_Hypothesis_var>& aNewHypVarList = myExistingHyps[ theDim ][ Algo ];
1353     for ( anIter = aNewHypVarList.begin(); anIter != aNewHypVarList.end(); ++anIter )
1354     {
1355       SMESH::SMESH_Hypothesis_var aHypVar = *anIter;
1356       if ( !aHypVar->_is_nil() && aHypName == aHypVar->GetName() )
1357       {
1358         anAlgoVar = aHypVar;
1359         break;
1360       }
1361     }
1362   }
1363
1364   return anAlgoVar._retn();
1365 }
1366
1367 //================================================================================
1368 /*!
1369  * \brief Reads parameters of edited mesh and assigns them to the dialog
1370  *
1371  * Reads parameters of edited mesh and assigns them to the dialog (called when
1372  * mesh is edited only)
1373  */
1374 //================================================================================
1375 void SMESHGUI_MeshOp::readMesh()
1376 {
1377   QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
1378   _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.latin1() );
1379   if ( !pObj )
1380     return;
1381
1382   // Get name of mesh if current object is sub-mesh
1383   SMESH::SMESH_subMesh_var aSubMeshVar =
1384       SMESH::SMESH_subMesh::_narrow( _CAST( SObject,pObj )->GetObject() );
1385   if ( !aSubMeshVar->_is_nil() )
1386   {
1387     SMESH::SMESH_Mesh_var aMeshVar =  aSubMeshVar->GetFather();
1388     if ( !aMeshVar->_is_nil() )
1389     {
1390       _PTR(SObject) aMeshSO = SMESH::FindSObject( aMeshVar );
1391       QString aMeshName = name( aMeshSO );
1392       myDlg->setObjectText( SMESHGUI_MeshDlg::Mesh, aMeshName );
1393     }
1394   }
1395
1396   // Get name of geometry object
1397   GEOM::GEOM_Object_var aGeomVar = SMESH::GetShapeOnMeshOrSubMesh( pObj );
1398   if ( !aGeomVar->_is_nil() )
1399   {
1400     _PTR(SObject) aGeomSO = studyDS()->FindObjectID( aGeomVar->GetStudyEntry() );
1401     QString aShapeName = name( aGeomSO );
1402     myDlg->setObjectText( SMESHGUI_MeshDlg::Geom, aShapeName );
1403   }
1404
1405   // Get hypotheses and algorithms assigned to the mesh/sub-mesh
1406   for ( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ )
1407   {
1408     // get algorithm
1409     QStringList anExisting;
1410     int aHypIndex = -1;
1411     existingHyps( dim, Algo, pObj, anExisting, myObjHyps[ dim ][ Algo ] );
1412     if ( myObjHyps[ dim ][ Algo ].count() > 0 )
1413     {
1414       // find algo index among available ones
1415       SMESH::SMESH_Hypothesis_var aVar = myObjHyps[ dim ][ Algo ].first();
1416       QString aHypTypeName = aVar->GetName();
1417       HypothesisData* algoData = SMESH::GetHypothesisData( aHypTypeName );
1418       aHypIndex = myAvailableHypData[ dim ][ Algo ].findIndex ( algoData );
1419     }
1420     setCurrentHyp( dim, Algo, aHypIndex );
1421     onAlgoSelected( aHypIndex, dim );
1422
1423     // get hypotheses
1424     for ( int hypType = MainHyp; hypType <= AddHyp; hypType++ )
1425     {
1426       // get hypotheses
1427       existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] );
1428       // find index of requered hypothesis among existing ones for this dimension and type
1429       int aHypIndex = -1;
1430       if ( myObjHyps[ dim ][ hypType ].count() > 0 )
1431         aHypIndex = find( myObjHyps[ dim ][ hypType ].first(),
1432                           myExistingHyps[ dim ][ hypType ] );
1433       setCurrentHyp( dim, hypType, aHypIndex );
1434     }
1435   }
1436 }
1437
1438 //================================================================================
1439 /*!
1440  * \brief Gets name of object
1441   * \param theSO - SObject
1442   * \retval QString - name of object
1443  *
1444  * Gets name of object
1445  */
1446 //================================================================================
1447 QString SMESHGUI_MeshOp::name( _PTR(SObject) theSO ) const
1448 {
1449   QString aResName;
1450   if ( theSO )
1451   {
1452     _PTR(GenericAttribute) anAttr;
1453     _PTR(AttributeName)    aNameAttr;
1454     if ( theSO->FindAttribute( anAttr, "AttributeName" ) )
1455     {
1456       aNameAttr = anAttr;
1457       aResName = aNameAttr->Value().c_str();
1458     }
1459   }
1460   return aResName;
1461 }
1462
1463 //================================================================================
1464 /*!
1465  * \brief Finds hypothesis in input list
1466   * \param theHyp - hypothesis to be found
1467   * \param theHypList - input list of hypotheses
1468   * \retval int - index of hypothesis or -1 if it is not found
1469  *
1470  * Finds position of hypothesis in input list
1471  */
1472 //================================================================================
1473 int SMESHGUI_MeshOp::find( const SMESH::SMESH_Hypothesis_var& theHyp,
1474                            const QValueList<SMESH::SMESH_Hypothesis_var>& theHypList ) const
1475 {
1476   int aRes = -1;
1477   if ( !theHyp->_is_nil() )
1478   {
1479     int i = 0;
1480     QValueList<SMESH::SMESH_Hypothesis_var>::const_iterator anIter;
1481     for ( anIter = theHypList.begin(); anIter != theHypList.end(); ++ anIter )
1482     {
1483       if ( theHyp->_is_equivalent( *anIter ) )
1484       {
1485         aRes = i;
1486         break;
1487       }
1488       i++;
1489     }
1490   }
1491   return aRes;
1492 }
1493
1494 //================================================================================
1495 /*!
1496  * \brief Edits mesh or sub-mesh
1497   * \param theMess - Output parameter intended for returning error message
1498   * \retval bool  - TRUE if mesh is edited succesfully, FALSE otherwise
1499  *
1500  * Assigns new name hypotheses and algoriths to the mesh or sub-mesh
1501  */
1502 //================================================================================
1503 bool SMESHGUI_MeshOp::editMeshOrSubMesh( QString& theMess )
1504 {
1505   theMess = "";
1506
1507   SMESH::SMESH_Gen_var aSMESHGen = SMESHGUI::GetSMESHGen();
1508   if ( aSMESHGen->_is_nil() )
1509     return false;
1510
1511   QString anObjEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Obj );
1512   _PTR(SObject) pObj = studyDS()->FindObjectID( anObjEntry.latin1() );
1513   if ( !pObj )
1514     return false;
1515
1516   SUIT_OverrideCursor aWaitCursor;
1517
1518   // Set new name
1519   SMESH::SetName( pObj, myDlg->objectText( SMESHGUI_MeshDlg::Obj ).latin1() );
1520
1521   // Assign new hypotheses and algorithms
1522   for ( int dim = SMESH::DIM_1D; dim <= SMESH::DIM_3D; dim++ )
1523   {
1524     if ( !isAccessibleDim( dim )) continue;
1525
1526     // find or create algorithm
1527     bool toDelete = false, toAdd = true;
1528     SMESH::SMESH_Hypothesis_var anAlgoVar = getAlgo( dim );
1529     if ( anAlgoVar->_is_nil() ) {
1530       toAdd = false;
1531     }
1532     if ( myObjHyps[ dim ][ Algo ].count() > 0 ) {
1533       SMESH::SMESH_Hypothesis_var anOldAlgo = myObjHyps[ dim ][ Algo ].first();
1534       if ( toAdd ) {
1535         if ( strcmp(anOldAlgo->GetName(), anAlgoVar->GetName()) == 0 ) {
1536           toAdd = false;
1537         } else {
1538           toDelete = true;
1539         }
1540       } else {
1541         toDelete = true;
1542       }
1543     }
1544     // remove old algorithm
1545     if ( toDelete ) {
1546       SMESH::RemoveHypothesisOrAlgorithmOnMesh ( pObj, myObjHyps[ dim ][ Algo ].first() );
1547       myObjHyps[ dim ][ Algo ].clear();
1548     }
1549
1550     // assign new algorithm
1551     if ( toAdd ) {
1552       SMESH::SMESH_Mesh_var aMeshVar =
1553         SMESH::SMESH_Mesh::_narrow( _CAST(SObject,pObj)->GetObject() );
1554       bool isMesh = !aMeshVar->_is_nil();
1555       if ( isMesh ) {
1556         SMESH::AddHypothesisOnMesh( aMeshVar, anAlgoVar );
1557       } else {
1558         SMESH::SMESH_subMesh_var aVar =
1559           SMESH::SMESH_subMesh::_narrow( _CAST(SObject,pObj)->GetObject() );
1560         if ( !aVar->_is_nil() )
1561           SMESH::AddHypothesisOnSubMesh( aVar, anAlgoVar );
1562       }
1563       myObjHyps[ dim ][ Algo ].append( anAlgoVar );
1564     }
1565
1566     // assign hypotheses
1567     for ( int hypType = MainHyp; hypType <= AddHyp; hypType++ )
1568     {
1569       int aNewHypIndex = currentHyp( dim, hypType );
1570       int anOldHypIndex = -1;
1571       if ( myObjHyps[ dim ][ hypType ].count() > 0 )
1572         anOldHypIndex = find( myObjHyps[ dim ][ hypType ].first(),
1573                               myExistingHyps[ dim ][ hypType ] );
1574       if ( aNewHypIndex != anOldHypIndex )
1575       {
1576         // remove old hypotheses
1577         if ( anOldHypIndex >= 0 ) {
1578           SMESH::RemoveHypothesisOrAlgorithmOnMesh(
1579             pObj, myExistingHyps[ dim ][ hypType ][ anOldHypIndex ] );
1580           myExistingHyps.remove( anOldHypIndex );
1581         }
1582
1583         // assign new hypotheses
1584         if ( aNewHypIndex != -1 )
1585         {
1586           SMESH::SMESH_Mesh_var aMeshVar =
1587               SMESH::SMESH_Mesh::_narrow( _CAST(SObject,pObj)->GetObject() );
1588           bool isMesh = !aMeshVar->_is_nil();
1589           if ( isMesh )
1590           {
1591             SMESH::AddHypothesisOnMesh(
1592               aMeshVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ] );
1593           }
1594           else
1595           {
1596             SMESH::SMESH_subMesh_var aVar =
1597               SMESH::SMESH_subMesh::_narrow( _CAST(SObject,pObj)->GetObject() );
1598             if ( !aVar->_is_nil() )
1599               SMESH::AddHypothesisOnSubMesh(
1600                 aVar, myExistingHyps[ dim ][ hypType ][ aNewHypIndex ] );
1601           }
1602         }
1603         // reread all hypotheses of mesh if necessary
1604         QStringList anExisting;
1605         existingHyps( dim, hypType, pObj, anExisting, myObjHyps[ dim ][ hypType ] );
1606       }
1607     }
1608   }
1609
1610   return true;
1611 }
1612
1613 //================================================================================
1614 /*!
1615  * \brief Verifies whether given operator is valid for this one
1616   * \param theOtherOp - other operation
1617   * \return Returns TRUE if the given operator is valid for this one, FALSE otherwise
1618 *
1619 * method redefined from base class verifies whether given operator is valid for
1620 * this one (i.e. can be started "above" this operator). In current implementation method
1621 * retuns false if theOtherOp operation is not intended for deleting objects or mesh
1622 * elements.
1623 */
1624 //================================================================================
1625 bool SMESHGUI_MeshOp::isValid( SUIT_Operation* theOp ) const
1626 {
1627   return SMESHGUI_Operation::isValid( theOp ) && !theOp->inherits( "SMESHGUI_MeshOp" );
1628 }
1629
1630 //================================================================================
1631 /*!
1632  * \brief SLOT. Is called when the user selects a way of geometry selection
1633   * \param theByMesh - true if the user wants to find geometry by mesh element
1634  */
1635 //================================================================================
1636
1637 void SMESHGUI_MeshOp::onGeomSelectionByMesh( bool theByMesh )
1638 {
1639   if ( theByMesh ) {
1640     if ( !myShapeByMeshOp ) {
1641       myShapeByMeshOp = new SMESHGUI_ShapeByMeshOp();
1642       connect(myShapeByMeshOp, SIGNAL(committed(SUIT_Operation*)),
1643               SLOT(onPublishShapeByMeshDlg(SUIT_Operation*)));
1644       connect(myShapeByMeshOp, SIGNAL(aborted(SUIT_Operation*)),
1645               SLOT(onCloseShapeByMeshDlg(SUIT_Operation*)));
1646     }
1647     // set mesh object to SMESHGUI_ShapeByMeshOp and start it
1648     QString aMeshEntry = myDlg->selectedObject( SMESHGUI_MeshDlg::Mesh );
1649     if ( _PTR(SObject) pMesh = studyDS()->FindObjectID( aMeshEntry.latin1() )) {
1650       SMESH::SMESH_Mesh_var aMeshVar =
1651         SMESH::SMESH_Mesh::_narrow( _CAST( SObject,pMesh )->GetObject() );
1652       if ( !aMeshVar->_is_nil() ) {
1653         myDlg->hide(); // stop processing selection
1654         myShapeByMeshOp->setModule( getSMESHGUI() );
1655         myShapeByMeshOp->setStudy( 0 ); // it's really necessary
1656         myShapeByMeshOp->SetMesh( aMeshVar );
1657         myShapeByMeshOp->start();
1658       }
1659     }
1660   }
1661 }
1662
1663 //================================================================================
1664 /*!
1665  * \brief SLOT. Is called when Ok is pressed in SMESHGUI_ShapeByMeshDlg
1666  */
1667 //================================================================================
1668
1669 void SMESHGUI_MeshOp::onPublishShapeByMeshDlg(SUIT_Operation* op)
1670 {
1671   if ( myShapeByMeshOp == op ) {
1672     myDlg->show();
1673     // Select a found geometry object
1674     GEOM::GEOM_Object_var aGeomVar = myShapeByMeshOp->GetShape();
1675     if ( !aGeomVar->_is_nil() )
1676     {
1677       QString ID = aGeomVar->GetStudyEntry();
1678       if ( _PTR(SObject) aGeomSO = studyDS()->FindObjectID( ID.latin1() )) {
1679         selectObject( aGeomSO );
1680         selectionDone();
1681       }
1682     }
1683   }
1684 }
1685
1686 //================================================================================
1687 /*!
1688  * \brief SLOT. Is called when Close is pressed in SMESHGUI_ShapeByMeshDlg
1689  */
1690 //================================================================================
1691
1692 void SMESHGUI_MeshOp::onCloseShapeByMeshDlg(SUIT_Operation* op)
1693 {
1694   if ( myShapeByMeshOp == op && myDlg ) {
1695     myDlg->show();
1696   }
1697 }
1698
1699 //================================================================================
1700 /*!
1701  * \brief Selects a SObject
1702   * \param theSObj - the SObject to select
1703  */
1704 //================================================================================
1705
1706 void SMESHGUI_MeshOp::selectObject( _PTR(SObject) theSObj ) const
1707 {
1708   if ( LightApp_SelectionMgr* sm = selectionMgr() ) {
1709     SALOME_ListIO anIOList;
1710     if ( theSObj ) {
1711       Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject
1712         ( theSObj->GetID().c_str(), "SMESH", theSObj->GetName().c_str() );
1713       anIOList.Append( anIO );
1714     }
1715     sm->setSelectedObjects( anIOList, false );
1716   }
1717 }