Salome HOME
Merge from V5_1_main 14/05/2010
[modules/smesh.git] / src / StdMeshersGUI / StdMeshersGUI_NbSegmentsCreator.cxx
1 //  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File   : StdMeshersGUI_NbSegmentsCreator.cxx
24 // Author : Open CASCADE S.A.S.
25 // SMESH includes
26 //
27 #include "StdMeshersGUI_NbSegmentsCreator.h"
28 #include "StdMeshersGUI_DistrTable.h"
29 #include "StdMeshersGUI_DistrPreview.h"
30 #include "StdMeshersGUI_SubShapeSelectorWdg.h"
31
32 #include <SMESHGUI.h>
33 #include <SMESHGUI_Utils.h>
34 #include <SMESHGUI_HypothesesUtils.h>
35 #include <SMESHGUI_SpinBox.h>
36
37 // IDL includes
38 #include CORBA_SERVER_HEADER(SMESH_BasicHypothesis)
39
40 // SALOME GUI includes
41 #include <SalomeApp_Tools.h>
42 #include <SalomeApp_IntSpinBox.h>
43 #include <QtxComboBox.h>
44
45 // Qt includes
46 #include <QLabel>
47 #include <QGroupBox>
48 #include <QFrame>
49 #include <QLineEdit>
50 #include <QButtonGroup>
51 #include <QRadioButton>
52 #include <QGridLayout>
53 #include <QVBoxLayout>
54 #include <QHBoxLayout>
55 #include <QApplication>
56
57 #define SPACING 6
58 #define MARGIN  11
59
60 StdMeshersGUI_NbSegmentsCreator::StdMeshersGUI_NbSegmentsCreator()
61 : StdMeshersGUI_StdHypothesisCreator( "NumberOfSegments" ),
62   myNbSeg( 0 ),
63   myDistr( 0 ),
64   myScale( 0 ),
65   myTable( 0 ),
66   myPreview( 0 ),
67   myExpr( 0 ),
68   myConvBox( 0 ),
69   myConv( 0 ),
70   myLScale( 0 ),
71   myLTable( 0 ),
72   myLExpr( 0 ),
73   myInfo( 0 ),
74   myGroupLayout( 0 ),
75   myTableRow( 0 ),
76   myPreviewRow( 0 )
77 {
78 }
79
80 StdMeshersGUI_NbSegmentsCreator::~StdMeshersGUI_NbSegmentsCreator()
81 {
82 }
83
84 bool StdMeshersGUI_NbSegmentsCreator::checkParams( QString& msg ) const
85 {
86   if( !SMESHGUI_GenericHypothesisCreator::checkParams( msg ) )
87     return false;
88   NbSegmentsHypothesisData data_old, data_new;
89   readParamsFromHypo( data_old );
90   readParamsFromWidgets( data_new );
91   bool res = storeParamsToHypo( data_new );
92   storeParamsToHypo( data_old );
93   res = myNbSeg->isValid( msg, true ) && res;
94   res = myScale->isValid( msg, true ) && res;
95   return res;
96 }
97
98 QFrame* StdMeshersGUI_NbSegmentsCreator::buildFrame()
99 {
100   QFrame* fr = new QFrame();
101
102   QVBoxLayout* lay = new QVBoxLayout( fr );
103   lay->setMargin( 0 );
104   lay->setSpacing( SPACING );
105
106   QGroupBox* GroupC1 = new QGroupBox( tr( "SMESH_ARGUMENTS" ), fr );
107   lay->addWidget( GroupC1 );
108
109   StdMeshers::StdMeshers_NumberOfSegments_var h =
110     StdMeshers::StdMeshers_NumberOfSegments::_narrow( hypothesis() );
111   myPreview = new StdMeshersGUI_DistrPreview( GroupC1, h.in() );
112
113   myGroupLayout = new QGridLayout( GroupC1 );
114   myGroupLayout->setSpacing( SPACING );
115   myGroupLayout->setMargin( MARGIN );
116   myGroupLayout->setColumnStretch( 0, 0 );
117   myGroupLayout->setColumnStretch( 1, 1 );
118
119   int row = 0;
120   // 0)  name
121   myName = 0;
122   if( isCreation() )
123   {
124     myName = new QLineEdit( GroupC1 );
125     myGroupLayout->addWidget( new QLabel( tr( "SMESH_NAME" ), GroupC1 ), row, 0 );
126     myGroupLayout->addWidget( myName, row, 1 );
127     row++;
128   }
129
130   // 1)  number of segments
131   myGroupLayout->addWidget( new QLabel( tr( "SMESH_NB_SEGMENTS_PARAM" ), GroupC1 ), row, 0 );
132   myNbSeg = new SalomeApp_IntSpinBox( GroupC1 );
133   myNbSeg->setMinimum( 1 );
134   myNbSeg->setMaximum( 9999 );
135   myGroupLayout->addWidget( myNbSeg, row, 1 );
136   row++;
137
138   // 2)  type of distribution
139   myGroupLayout->addWidget( new QLabel( tr( "SMESH_DISTR_TYPE" ), GroupC1 ), row, 0 );
140   myDistr = new QtxComboBox( GroupC1 );
141   QStringList types;
142   types.append( tr( "SMESH_DISTR_REGULAR" ) );
143   types.append( tr( "SMESH_DISTR_SCALE"   ) );
144   types.append( tr( "SMESH_DISTR_TAB"     ) );
145   types.append( tr( "SMESH_DISTR_EXPR"    ) );
146   myDistr->addItems( types );
147   myGroupLayout->addWidget( myDistr, row, 1 );
148   row++;
149
150   // 3)  scale
151   myGroupLayout->addWidget( myLScale = new QLabel( tr( "SMESH_NB_SEGMENTS_SCALE_PARAM" ), GroupC1 ), row, 0 );
152   myScale = new SMESHGUI_SpinBox( GroupC1 );
153   myScale->RangeStepAndValidator( 1E-5, 1E+5, 0.1, "parametric_precision" );
154   myGroupLayout->addWidget( myScale, row, 1 );
155   row++;
156
157   myInfo = new QLabel( tr( "SMESH_FUNC_DOMAIN" ), GroupC1 );
158   myGroupLayout->addWidget( myInfo, row, 0, 1, 2 );
159   row++;
160   
161   // 4)  table
162   myGroupLayout->addWidget( myLTable = new QLabel( tr( "SMESH_TAB_FUNC" ), GroupC1 ), row, 0 );
163   myTable = new StdMeshersGUI_DistrTableFrame( GroupC1 );
164   myGroupLayout->addWidget( myTable, row, 1 );
165   myGroupLayout->setRowStretch( row, 1 );
166   myTableRow = row;
167   row++;
168
169   // 5)  expression
170   myGroupLayout->addWidget( myLExpr = new QLabel( tr( "SMESH_EXPR_FUNC" ), GroupC1 ), row, 0 );
171   myExpr = new QLineEdit( GroupC1 );
172   myGroupLayout->addWidget( myExpr, row, 1 );
173   row++;
174
175   // 6)  conversion (radiogroup)
176   myConvBox = new QGroupBox( tr( "SMESH_CONV_MODE" ), GroupC1 );
177   myConv = new QButtonGroup( GroupC1 );
178
179   QHBoxLayout* convLay = new QHBoxLayout( myConvBox );
180   convLay->setMargin( MARGIN );
181   convLay->setSpacing( SPACING );
182
183   QRadioButton* rbExp = new QRadioButton( tr( "SMESH_EXP_MODE" ), myConvBox );
184   QRadioButton* myCutNeg = new QRadioButton( tr( "SMESH_CUT_NEG_MODE" ), myConvBox );
185
186   convLay->addWidget( rbExp );
187   convLay->addWidget( myCutNeg );
188   myConv->addButton( rbExp, 0 );
189   myConv->addButton( myCutNeg, 1 );
190
191   myGroupLayout->addWidget( myConvBox, row, 0, 1, 2 );
192   row++;
193
194   // 7) distribution preview
195   myGroupLayout->addWidget( myPreview, row, 0, 1, 2 );
196   myGroupLayout->setRowStretch( row, 1 );
197   myPreviewRow = row;
198   row++;
199
200   // 8) reverce edge parameters
201   myReversedEdgesBox = new QGroupBox(tr( "SMESH_REVERSED_EDGES" ), fr);
202   QHBoxLayout* edgeLay = new QHBoxLayout( myReversedEdgesBox );
203
204   myDirectionWidget = new StdMeshersGUI_SubShapeSelectorWdg();
205   QString aGeomEntry = getShapeEntry();
206   QString aMainEntry = getMainShapeEntry();
207   if ( aGeomEntry == "" )
208     aGeomEntry = h->GetObjectEntry();
209   myDirectionWidget->SetGeomShapeEntry( aGeomEntry );
210   myDirectionWidget->SetMainShapeEntry( aMainEntry );
211   myDirectionWidget->SetListOfIDs( h->GetReversedEdges() );
212   edgeLay->addWidget( myDirectionWidget );
213
214   lay->addWidget( myReversedEdgesBox );
215
216   connect( myNbSeg, SIGNAL( valueChanged( const QString& ) ), this, SLOT( onValueChanged() ) );
217   connect( myDistr, SIGNAL( activated( int ) ), this, SLOT( onValueChanged() ) );
218   connect( myTable, SIGNAL( valueChanged( int, int ) ), this, SLOT( onValueChanged() ) );
219   connect( myExpr,  SIGNAL( textChanged( const QString& ) ), this, SLOT( onValueChanged() ) );
220   connect( myConv,  SIGNAL( buttonClicked( int ) ), this, SLOT( onValueChanged() ) );
221
222   return fr;
223 }
224
225 void StdMeshersGUI_NbSegmentsCreator::retrieveParams() const
226 {
227   NbSegmentsHypothesisData data;
228   readParamsFromHypo( data );
229
230   if( myName )
231     myName->setText( data.myName );
232   if(data.myNbSegVarName.isEmpty())
233     myNbSeg->setValue( data.myNbSeg );
234   else
235     myNbSeg->setText( data.myNbSegVarName );
236   
237   myDistr->setCurrentIndex( data.myDistrType );
238   if(data.myScaleVarName.isEmpty())
239     myScale->setValue( data.myScale );
240   else
241     myScale->setText( data.myScaleVarName );
242   myConv->button( data.myConv )->setChecked( true );
243   myTable->setFuncMinValue(myConv->checkedId()==0 ? -1E20 : 0);
244   myTable->setData( data.myTable );
245   myExpr->setText( data.myExpr );
246
247   if ( dlg() )
248     dlg()->setMinimumSize( dlg()->minimumSizeHint().width(), dlg()->minimumSizeHint().height() );
249 }
250
251 QString StdMeshersGUI_NbSegmentsCreator::storeParams() const
252 {
253   NbSegmentsHypothesisData data;
254   readParamsFromWidgets( data );
255   storeParamsToHypo( data );
256     
257   QString valStr = QString::number( data.myNbSeg ) += "; ";
258
259   enum DistrType
260   {
261     Regular, //!< equidistant distribution
262     Scale,   //!< scale distribution
263     TabFunc, //!< distribution with density function presented by table
264     ExprFunc //!< distribution with density function presented by expression
265   };
266   bool hasConv = false;
267   switch ( data.myDistrType ) {
268   case Regular :
269     valStr += tr("SMESH_DISTR_REGULAR");
270     break;
271   case Scale   : 
272     valStr += tr("SMESH_NB_SEGMENTS_SCALE_PARAM") + " = " + QString::number( data.myScale );\
273     break;
274   case TabFunc : {
275     //valStr += tr("SMESH_TAB_FUNC");
276     bool param = true;
277     for( int i=0; i < data.myTable.length(); i++, param = !param ) {
278       if ( param )
279         valStr += "[";
280       valStr += QString::number( data.myTable[ i ]);
281       valStr += ( param ? "," : "]" );
282     }
283     hasConv = true;
284     break;
285   }
286   case ExprFunc:
287     valStr += data.myExpr;
288     hasConv = true;
289     break;
290   }
291   if ( hasConv )
292     if ( data.myConv )
293       valStr += "; " + tr("SMESH_CUT_NEG_MODE");
294     else
295       valStr += "; " + tr("SMESH_EXP_MODE");
296
297   return valStr;
298 }
299
300 bool StdMeshersGUI_NbSegmentsCreator::readParamsFromHypo( NbSegmentsHypothesisData& h_data ) const
301 {
302   StdMeshers::StdMeshers_NumberOfSegments_var h =
303     StdMeshers::StdMeshers_NumberOfSegments::_narrow( initParamsHypothesis() );
304
305   h_data.myName = hypName();
306
307   h_data.myNbSeg = (int) h->GetNumberOfSegments();
308   
309   SMESH::ListOfParameters_var aParameters = h->GetLastParameters();
310
311   h_data.myNbSegVarName  = (aParameters->length() > 0) ? QString(aParameters[0].in()) : QString("");
312
313   int distr = (int) h->GetDistrType();
314   h_data.myDistrType = distr;
315   h_data.myScale = distr==1 ? h->GetScaleFactor() : 1.0;
316   
317   if(distr==1){
318     h_data.myScaleVarName  = (aParameters->length() > 1) ? QString(aParameters[1].in()) : QString("");
319   }
320   else 
321     h_data.myScaleVarName = QString("");
322
323   if( distr==2 )
324   {
325     SMESH::double_array* a = h->GetTableFunction();
326     h_data.myTable = *a;
327     delete a;
328   }
329   else
330   {
331     SMESH::double_array& a = h_data.myTable;
332     // by default, constant table function f(t)=1
333     a.length( 4 );
334     a[0] = 0.0; a[1] = 1.0;
335     a[2] = 1.0; a[3] = 1.0; 
336   }
337
338   h_data.myExpr = distr==3 ? h->GetExpressionFunction() : "1";
339   h_data.myConv = distr==2 || distr==3 ? h->ConversionMode() : 1; /*cut negative by default*/
340
341   return true;
342 }
343
344 bool StdMeshersGUI_NbSegmentsCreator::storeParamsToHypo( const NbSegmentsHypothesisData& h_data ) const
345 {
346   StdMeshers::StdMeshers_NumberOfSegments_var h =
347     StdMeshers::StdMeshers_NumberOfSegments::_narrow( hypothesis() );
348
349   bool ok = true;
350   try
351   {
352     if( isCreation() )
353       SMESH::SetName( SMESH::FindSObject( h ), h_data.myName.toLatin1().data() );
354
355     QStringList aVariablesList;
356     aVariablesList.append(h_data.myNbSegVarName);
357
358     h->SetNumberOfSegments( h_data.myNbSeg );
359     int distr = h_data.myDistrType;
360     h->SetDistrType( distr );
361     
362     if( distr==1 ) {
363       h->SetScaleFactor( h_data.myScale );
364       aVariablesList.append(h_data.myScaleVarName);
365     }
366     if( distr==2 || distr==3 )
367       h->SetConversionMode( h_data.myConv );
368
369     if( distr==1 || distr==2 || distr==3 ) {
370       h->SetReversedEdges( myDirectionWidget->GetListOfIDs() );
371       h->SetObjectEntry( myDirectionWidget->GetMainShapeEntry() );
372     }
373
374     if( distr==2 )
375       h->SetTableFunction( h_data.myTable );
376
377     if( distr==3 )
378       h->SetExpressionFunction( h_data.myExpr.toLatin1().data() );
379     //setting of function must follow after setConversionMode, because otherwise
380     //the function will be checked with old conversion mode, so that it may occurs
381     //unexpected errors for user
382
383     h->SetParameters(aVariablesList.join(":").toLatin1().constData());
384   }
385   catch(const SALOME::SALOME_Exception& ex)
386   {
387     SalomeApp_Tools::QtCatchCorbaException(ex);
388     ok = false;
389   }
390   return ok;
391 }
392
393 bool StdMeshersGUI_NbSegmentsCreator::readParamsFromWidgets( NbSegmentsHypothesisData& h_data ) const
394 {
395   h_data.myName      = myName ? myName->text() : "";
396   h_data.myNbSeg     = myNbSeg->value();
397   h_data.myNbSegVarName =  myNbSeg->text();
398   h_data.myScaleVarName =  myScale->text();
399   h_data.myDistrType = myDistr->currentIndex();
400   h_data.myConv      = myConv->checkedId();
401   h_data.myScale     = myScale->value();
402   myTable->data( h_data.myTable );
403   h_data.myExpr      = myExpr->text();
404   return true;
405 }
406
407 void StdMeshersGUI_NbSegmentsCreator::onValueChanged()
408 {
409   int distr = myDistr->currentIndex();
410
411 /*  if( distr==2 ) //table func
412     myCutNeg->setText( tr( "SMESH_NO_CONV" ) );
413   else if( distr==3 )
414     myCutNeg->setText( tr( "SMESH_CUT_NEG_MODE" ) );*/
415
416   if( distr==2 && sender()==myConv ) //table func
417   {
418     myTable->setFuncMinValue( myConv->checkedId()==0 ? -1E20 : 0 );
419     SMESH::double_array arr;
420     myTable->data( arr );
421     myTable->setData( arr ); //update data in table
422   }
423
424   myScale->setShown( distr==1 );
425   myLScale->setShown( distr==1 );
426   myReversedEdgesBox->setShown( !distr==0 );
427   myDirectionWidget->showPreview( !distr==0 );
428
429   bool isFunc = distr==2 || distr==3;
430   myPreview->setShown( isFunc );
431   myGroupLayout->setRowStretch( myPreviewRow, isFunc ? 1 : 0 );
432
433   myConvBox->setShown( isFunc );
434
435   if( distr==2 )
436     myTable->show();
437   else
438     myTable->hide();
439   myLTable->setShown( distr==2 );
440   myGroupLayout->setRowStretch( myTableRow, distr==2 ? 1 : 0 );
441
442   myExpr->setShown( distr==3 );
443   myLExpr->setShown( distr==3 );
444   myInfo->setShown( isFunc );
445
446   //change of preview
447   int nbSeg = myNbSeg->value();
448   if( distr==2 ) //preview for table-described function
449   {
450     SMESH::double_array a;
451     myTable->data( a );
452     myPreview->setParams( a, nbSeg, false );
453   }
454   else if( distr==3 ) //preview for analytic-described function
455     myPreview->setParams( myExpr->text(), nbSeg, 100, false );
456
457   if( isFunc )
458     myPreview->setConversion( StdMeshersGUI_DistrPreview::Conversion( myConv->checkedId() ) );
459
460   if ( (QtxComboBox*)sender() == myDistr && dlg() ) {
461     QApplication::instance()->processEvents();
462     myGroupLayout->invalidate();
463     dlg()->layout()->invalidate();
464     dlg()->updateGeometry();
465     dlg()->setMinimumSize( dlg()->minimumSizeHint() );
466     dlg()->resize( dlg()->minimumSize() );
467     QApplication::instance()->processEvents();
468   }
469 }