Salome HOME
Merge remote branch 'origin/gdd/translations'
[modules/smesh.git] / src / StdMeshersGUI / StdMeshersGUI_NbSegmentsCreator.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
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   fr->setMinimumWidth(460);
102
103   QVBoxLayout* lay = new QVBoxLayout( fr );
104   lay->setMargin( 0 );
105   lay->setSpacing( SPACING );
106
107   QGroupBox* GroupC1 = new QGroupBox( tr( "SMESH_ARGUMENTS" ), fr );
108   lay->addWidget( GroupC1 );
109
110   StdMeshers::StdMeshers_NumberOfSegments_var h =
111     StdMeshers::StdMeshers_NumberOfSegments::_narrow( hypothesis() );
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
131   // 1)  number of segments
132   myGroupLayout->addWidget( new QLabel( tr( "SMESH_NB_SEGMENTS_PARAM" ), GroupC1 ), row, 0 );
133   myNbSeg = new SalomeApp_IntSpinBox( GroupC1 );
134   myNbSeg->setMinimum( 1 );
135   myNbSeg->setMaximum( 9999 );
136   myGroupLayout->addWidget( myNbSeg, row, 1 );
137   row++;
138
139   
140   // 2)  type of distribution
141   myGroupLayout->addWidget( new QLabel( tr( "SMESH_DISTR_TYPE" ), GroupC1 ), row, 0 );
142   myDistr = new QtxComboBox( GroupC1 );
143   QStringList types;
144   types.append( tr( "SMESH_DISTR_REGULAR" ) );
145   types.append( tr( "SMESH_DISTR_SCALE"   ) );
146   types.append( tr( "SMESH_DISTR_TAB"     ) );
147   types.append( tr( "SMESH_DISTR_EXPR"    ) );
148   myDistr->addItems( types );
149   myGroupLayout->addWidget( myDistr, row, 1 );
150   row++;
151
152   
153   // 3)  scale
154   myGroupLayout->addWidget( myLScale = new QLabel( tr( "SMESH_NB_SEGMENTS_SCALE_PARAM" ), GroupC1 ), row, 0 );
155   myScale = new SMESHGUI_SpinBox( GroupC1 );
156   myScale->RangeStepAndValidator( 1E-5, 1E+5, 0.1, "parametric_precision" );
157   myGroupLayout->addWidget( myScale, row, 1 );
158   row++;
159
160   
161   // 4) Distribution definition
162   QGridLayout* myDistLayout = new QGridLayout(GroupC1);
163   myGroupLayout->addLayout( myDistLayout, row, 0, 1, 2 );
164   myGroupLayout->setRowStretch( row, 1 );
165   row ++;
166
167        // a)  expression
168   QHBoxLayout* myExprLayout = new QHBoxLayout(GroupC1);
169   myExprLayout->addWidget( myLExpr = new QLabel( "f(t)=", GroupC1 ), 0);
170   myExpr = new QLineEdit( GroupC1 );
171   myExprLayout->addWidget( myExpr,1);
172   myDistLayout->addLayout(myExprLayout,1 ,0);
173   myDistLayout->setRowStretch(2, 1);
174
175        // b)  warning
176   myInfo = new QLabel( tr( "SMESH_FUNC_DOMAIN" ), GroupC1 );
177   myDistLayout->addWidget( myInfo, 0, 0, 1, 2);
178   
179        // c)  table
180   myTable = new StdMeshersGUI_DistrTableFrame( GroupC1 );
181   myDistLayout->addWidget( myTable, 1, 0, 2, 1 );
182
183        // d) preview
184   myPreview = new StdMeshersGUI_DistrPreview( GroupC1, h.in() );  
185   myPreview->setMinimumHeight(220);
186   myDistLayout->addWidget( myPreview, 1, 1, 2, 1 );
187   
188   // 5)  conversion (radiogroup)
189   myConvBox = new QGroupBox( tr( "SMESH_CONV_MODE" ), GroupC1 );
190   myConv = new QButtonGroup( GroupC1 );
191
192   QHBoxLayout* convLay = new QHBoxLayout( myConvBox );
193   convLay->setMargin( MARGIN );
194   convLay->setSpacing( SPACING );
195
196   QRadioButton* rbExp = new QRadioButton( tr( "SMESH_EXP_MODE" ), myConvBox );
197   QRadioButton* myCutNeg = new QRadioButton( tr( "SMESH_CUT_NEG_MODE" ), myConvBox );
198
199   convLay->addWidget( rbExp );
200   convLay->addWidget( myCutNeg );
201   myConv->addButton( rbExp, 0 );
202   myConv->addButton( myCutNeg, 1 );
203
204   myGroupLayout->addWidget( myConvBox, row, 0, 1, 2 );
205   row++;
206
207
208   // 6) reverse edge parameters
209   myReversedEdgesBox = new QGroupBox(tr( "SMESH_REVERSED_EDGES" ), fr);
210   QHBoxLayout* edgeLay = new QHBoxLayout( myReversedEdgesBox );
211
212   myDirectionWidget = new StdMeshersGUI_SubShapeSelectorWdg( myReversedEdgesBox );
213   QString aGeomEntry = getShapeEntry();
214   QString aMainEntry = getMainShapeEntry();
215   if ( aGeomEntry == "" )
216     aGeomEntry = h->GetObjectEntry();
217   myDirectionWidget->SetGeomShapeEntry( aGeomEntry );
218   myDirectionWidget->SetMainShapeEntry( aMainEntry );
219   myDirectionWidget->SetListOfIDs( h->GetReversedEdges() );
220   edgeLay->addWidget( myDirectionWidget );
221
222   lay->addWidget( myReversedEdgesBox );
223   lay->setStretchFactor( GroupC1, 2);
224   lay->setStretchFactor( myReversedEdgesBox, 1);
225   
226   connect( myNbSeg, SIGNAL( valueChanged( const QString& ) ), this, SLOT( onValueChanged() ) );
227   connect( myDistr, SIGNAL( activated( int ) ), this, SLOT( onValueChanged() ) );
228   connect( myTable, SIGNAL( valueChanged( int, int ) ), this, SLOT( onValueChanged() ) );
229   connect( myExpr,  SIGNAL( textChanged( const QString& ) ), this, SLOT( onValueChanged() ) );
230   connect( myConv,  SIGNAL( buttonClicked( int ) ), this, SLOT( onValueChanged() ) );
231
232   return fr;
233 }
234
235 void StdMeshersGUI_NbSegmentsCreator::retrieveParams() const
236 {
237   NbSegmentsHypothesisData data;
238   readParamsFromHypo( data );
239
240   if( myName )
241     myName->setText( data.myName );
242   if(data.myNbSegVarName.isEmpty())
243     myNbSeg->setValue( data.myNbSeg );
244   else
245     myNbSeg->setText( data.myNbSegVarName );
246   
247   myDistr->setCurrentIndex( data.myDistrType );
248   if(data.myScaleVarName.isEmpty())
249     myScale->setValue( data.myScale );
250   else
251     myScale->setText( data.myScaleVarName );
252   myConv->button( data.myConv )->setChecked( true );
253   myTable->setFuncMinValue(myConv->checkedId()==0 ? -1E20 : 0);
254   myTable->setData( data.myTable );
255   myExpr->setText( data.myExpr );
256
257   if ( dlg() )
258     dlg()->setMinimumSize( dlg()->minimumSizeHint().width(), dlg()->minimumSizeHint().height() );
259 }
260
261 QString StdMeshersGUI_NbSegmentsCreator::storeParams() const
262 {
263   NbSegmentsHypothesisData data;
264   readParamsFromWidgets( data );
265   storeParamsToHypo( data );
266     
267   QString valStr = QString::number( data.myNbSeg ) += "; ";
268
269   enum DistrType
270   {
271     Regular, //!< equidistant distribution
272     Scale,   //!< scale distribution
273     TabFunc, //!< distribution with density function presented by table
274     ExprFunc //!< distribution with density function presented by expression
275   };
276   bool hasConv = false;
277   switch ( data.myDistrType ) {
278   case Regular :
279     valStr += tr("SMESH_DISTR_REGULAR");
280     break;
281   case Scale   : 
282     valStr += tr("SMESH_NB_SEGMENTS_SCALE_PARAM") + " = " + QString::number( data.myScale );\
283     break;
284   case TabFunc : {
285     //valStr += tr("SMESH_TAB_FUNC");
286     bool param = true;
287     for( int i=0; i < data.myTable.length(); i++, param = !param ) {
288       if ( param )
289         valStr += "[";
290       valStr += QString::number( data.myTable[ i ]);
291       valStr += ( param ? "," : "]" );
292     }
293     hasConv = true;
294     break;
295   }
296   case ExprFunc:
297     valStr += data.myExpr;
298     hasConv = true;
299     break;
300   }
301   if ( hasConv )
302   {
303     if ( data.myConv )
304       valStr += "; " + tr("SMESH_CUT_NEG_MODE");
305     else
306       valStr += "; " + tr("SMESH_EXP_MODE");
307   }
308
309   return valStr;
310 }
311
312 bool StdMeshersGUI_NbSegmentsCreator::readParamsFromHypo( NbSegmentsHypothesisData& h_data ) const
313 {
314   StdMeshers::StdMeshers_NumberOfSegments_var h =
315     StdMeshers::StdMeshers_NumberOfSegments::_narrow( initParamsHypothesis() );
316
317   h_data.myName = hypName();
318
319   h_data.myNbSeg = (int) h->GetNumberOfSegments();
320
321   CORBA::String_var aVaribaleName = h->GetVarParameter( "SetNumberOfSegments" );
322   h_data.myNbSegVarName = aVaribaleName.in();
323
324   int distr = (int) h->GetDistrType();
325   h_data.myDistrType = distr;
326   h_data.myScale = distr==1 ? h->GetScaleFactor() : 1.0;
327   
328   if(distr==1) {
329     aVaribaleName = h->GetVarParameter( "SetScaleFactor" );
330     h_data.myScaleVarName = aVaribaleName.in();
331   }
332   else 
333     h_data.myScaleVarName = QString("");
334
335   if( distr==2 )
336   {
337     SMESH::double_array* a = h->GetTableFunction();
338     h_data.myTable = *a;
339     delete a;
340   }
341   else
342   {
343     SMESH::double_array& a = h_data.myTable;
344     // by default, constant table function f(t)=1
345     a.length( 4 );
346     a[0] = 0.0; a[1] = 1.0;
347     a[2] = 1.0; a[3] = 1.0; 
348   }
349
350   h_data.myExpr = distr==3 ? h->GetExpressionFunction() : "1";
351   h_data.myConv = distr==2 || distr==3 ? h->ConversionMode() : 1; /*cut negative by default*/
352
353   return true;
354 }
355
356 bool StdMeshersGUI_NbSegmentsCreator::storeParamsToHypo( const NbSegmentsHypothesisData& h_data ) const
357 {
358   StdMeshers::StdMeshers_NumberOfSegments_var h =
359     StdMeshers::StdMeshers_NumberOfSegments::_narrow( hypothesis() );
360
361   bool ok = true;
362   try
363   {
364     if( isCreation() )
365       SMESH::SetName( SMESH::FindSObject( h ), h_data.myName.toLatin1().data() );
366
367     h->SetVarParameter( h_data.myNbSegVarName.toLatin1().constData(), "SetNumberOfSegments" );
368     h->SetNumberOfSegments( h_data.myNbSeg );
369     int distr = h_data.myDistrType;
370     h->SetDistrType( distr );
371     
372     if( distr==1 ) {
373       h->SetVarParameter( h_data.myScaleVarName.toLatin1().constData(), "SetScaleFactor" );
374       h->SetScaleFactor( h_data.myScale );
375     }
376     if( distr==2 || distr==3 )
377       h->SetConversionMode( h_data.myConv );
378
379     if( distr==1 || distr==2 || distr==3 ) {
380       h->SetReversedEdges( myDirectionWidget->GetListOfIDs() );
381       h->SetObjectEntry( myDirectionWidget->GetMainShapeEntry() );
382     }
383
384     if( distr==2 )
385       h->SetTableFunction( h_data.myTable );
386
387     if( distr==3 )
388       h->SetExpressionFunction( h_data.myExpr.toLatin1().data() );
389     //setting of function must follow after setConversionMode, because otherwise
390     //the function will be checked with old conversion mode, so that it may occurs
391     //unexpected errors for user
392   }
393   catch(const SALOME::SALOME_Exception& ex)
394   {
395     SalomeApp_Tools::QtCatchCorbaException(ex);
396     ok = false;
397   }
398   return ok;
399 }
400
401 bool StdMeshersGUI_NbSegmentsCreator::readParamsFromWidgets( NbSegmentsHypothesisData& h_data ) const
402 {
403   h_data.myName      = myName ? myName->text() : "";
404   h_data.myNbSeg     = myNbSeg->value();
405   h_data.myNbSegVarName =  myNbSeg->text();
406   h_data.myScaleVarName =  myScale->text();
407   h_data.myDistrType = myDistr->currentIndex();
408   h_data.myConv      = myConv->checkedId();
409   h_data.myScale     = myScale->value();
410   myTable->data( h_data.myTable );
411   h_data.myExpr      = myExpr->text();
412   return true;
413 }
414
415 void StdMeshersGUI_NbSegmentsCreator::onValueChanged()
416 {
417   int distr = myDistr->currentIndex();
418
419 /*  if( distr==2 ) //table func
420     myCutNeg->setText( tr( "SMESH_NO_CONV" ) );
421   else if( distr==3 )
422     myCutNeg->setText( tr( "SMESH_CUT_NEG_MODE" ) );*/
423
424   if( distr==2 && sender()==myConv ) //table func
425   {
426     myTable->setFuncMinValue( myConv->checkedId()==0 ? -1E20 : 0 );
427     SMESH::double_array arr;
428     myTable->data( arr );
429     myTable->setData( arr ); //update data in table
430   }
431
432   myScale->setShown( distr==1 );
433   myLScale->setShown( distr==1 );
434   myReversedEdgesBox->setShown( !distr==0 );
435   myDirectionWidget->showPreview( !distr==0 );
436
437   bool isFunc = distr==2 || distr==3;
438   myPreview->setShown( isFunc );
439   myConvBox->setShown( isFunc );
440   
441   myTable->setShown( distr==2 );
442   myExpr->setShown( distr==3 );
443   myLExpr->setShown( distr==3 );
444   myInfo->setShown( distr==3);
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 }