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