1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : StdMeshersGUI_CartesianParamCreator.cxx
23 // Author : Open CASCADE S.A.S.
26 #include "StdMeshersGUI_CartesianParamCreator.h"
29 #include <SMESHGUI_Utils.h>
30 #include <SMESHGUI_HypothesesUtils.h>
31 #include <SMESHGUI_SpinBox.h>
34 #include CORBA_SERVER_HEADER(SMESH_BasicHypothesis)
36 // SALOME GUI includes
37 #include <SalomeApp_Tools.h>
38 #include <SalomeApp_IntSpinBox.h>
39 #include <QtxComboBox.h>
42 #include <QAbstractItemModel>
43 #include <QApplication>
44 #include <QButtonGroup>
45 #include <QGridLayout>
47 #include <QHBoxLayout>
50 #include <QListWidget>
51 #include <QModelIndex>
52 #include <QRadioButton>
54 #include <QStyleOptionViewItem>
55 #include <QTreeWidget>
56 #include <QTreeWidgetItem>
57 #include <QVBoxLayout>
58 #include <QPushButton>
64 namespace StdMeshersGUI
66 enum { COORD_BUT = 0, SPACING_BUT };
68 //================================================================================
70 * \brief get spacing definition from a tree item
72 //================================================================================
74 void getFromItem(QTreeWidgetItem * item, double& t0, double& t1, QString& fun )
78 t0 = item->text( 0 ).split(' ')[0].toDouble();
79 t1 = item->data( 0, Qt::UserRole ).toDouble();
80 fun = item->text( 1 );
84 //================================================================================
86 * \brief set spacing definition to a tree item
88 //================================================================================
90 QTreeWidgetItem* setToItem(double t0, double t1, const QString& fun, QTreeWidgetItem * item)
92 if ( !item ) item = new QTreeWidgetItem;
93 item->setText( 0, QString( "%1 - %2" ).arg( t0 ).arg( t1 ));
94 item->setData( 0, Qt::UserRole, t1 );
95 item->setText( 1, fun );
96 item->setFlags( item->flags() | Qt::ItemIsEditable );
100 //================================================================================
102 * \brief Retrieves coordinate value from a list item
104 //================================================================================
106 double coordFromItem( QListWidgetItem * item )
108 return item ? item->data( Qt::UserRole ).toDouble() : 0;
111 //================================================================================
113 * \brief Sets coordinate value to a list item
115 //================================================================================
117 QListWidgetItem* coordToItem( double coord, QListWidgetItem * item )
119 if ( !item ) item = new QListWidgetItem;
120 item->setText( QString::number( coord ));
121 item->setData( Qt::UserRole, coord );
122 item->setFlags( item->flags() | Qt::ItemIsEditable );
126 //================================================================================
129 * \param theParent - Parent widget for this tab
131 * Makes tab's look and feel
133 //================================================================================
135 GridAxisTab::GridAxisTab( QWidget* theParent,const int axisIndex ):
136 QFrame( theParent ), myAxisIndex( axisIndex )
138 // 1) Grid definition mode
139 myModeGroup = new QButtonGroup( this );
140 QGroupBox* modeBox = new QGroupBox( tr( "GRID_DEF_MODE" ), this );
141 QHBoxLayout* modeLay = new QHBoxLayout( modeBox );
142 modeLay->setMargin( MARGIN );
143 modeLay->setSpacing( SPACING );
145 QRadioButton* coordModeBtn = new QRadioButton( tr( "SMESH_COORDINATES" ), modeBox );
146 QRadioButton* spacModeBtn = new QRadioButton( tr( "SPACING" ), modeBox );
148 modeLay->addWidget( coordModeBtn );
149 modeLay->addWidget( spacModeBtn );
150 myModeGroup->addButton( coordModeBtn, COORD_BUT );
151 myModeGroup->addButton( spacModeBtn, SPACING_BUT );
154 myInsertBtn = new QPushButton( tr("INSERT"), this);
155 myDeleteBtn = new QPushButton( tr("SMESH_BUT_DELETE"), this);
157 myStepLabel = new QLabel( tr("COORD_STEP"));
158 myStepSpin = new SMESHGUI_SpinBox( this );
159 myStepSpin->setAcceptNames( false ); // No Notebook variables allowed
160 myStepSpin->RangeStepAndValidator();
161 myStepSpin->SetStep( 1. );
162 myStepSpin->SetValue( myStep = 1. );
164 // 3) Coodrinates/Spacing group
165 QFrame* csFrame = new QFrame( this );
166 QVBoxLayout* scLay = new QVBoxLayout( csFrame );
167 scLay->setMargin( 0 );
168 scLay->setSpacing( SPACING );
171 mySpacingTreeWdg = new QTreeWidget( csFrame );
172 mySpacingTreeWdg->setColumnCount(2);
173 mySpacingTreeWdg->setHeaderLabels( QStringList() << tr( "SMESH_RANGE" ) << QString( "f(t)" ));
174 mySpacingTreeWdg->setColumnWidth( 1, 40 );
175 mySpacingTreeWdg->setColumnWidth( 2, 30 );
176 mySpacingTreeWdg->setItemDelegate( new LineDelegate( mySpacingTreeWdg ));
177 scLay->addWidget( mySpacingTreeWdg );
180 myCoordList = new QListWidget( csFrame );
181 myCoordList->setItemDelegate( new LineDelegate( myCoordList ));
182 scLay->addWidget( myCoordList );
186 QGridLayout* axisTabLayout = new QGridLayout( this );
187 axisTabLayout->setMargin( MARGIN );
188 axisTabLayout->setSpacing( SPACING );
190 axisTabLayout->addWidget( modeBox , 0, 0, 1, 3 );
191 axisTabLayout->addWidget( myInsertBtn , 1, 0, 1, 2 );
192 axisTabLayout->addWidget( myDeleteBtn , 2, 0, 1, 2 );
193 axisTabLayout->addWidget( myStepLabel, 3, 0 );
194 axisTabLayout->addWidget( myStepSpin , 3, 1 );
195 axisTabLayout->addWidget( csFrame , 1, 2, 4, 1 );
197 axisTabLayout->setRowStretch( 4, 1 );
200 connect( myInsertBtn, SIGNAL( clicked() ), SLOT( onInsert() ));
201 connect( myDeleteBtn, SIGNAL( clicked() ), SLOT( onDelete() ));
202 connect( myModeGroup, SIGNAL( buttonClicked ( int )), SLOT( onMode(int)));
203 connect( mySpacingTreeWdg, SIGNAL( itemSelectionChanged()), SLOT( updateButtons() ));
204 connect( myCoordList, SIGNAL( itemSelectionChanged()), SLOT( updateButtons() ));
205 connect( myStepSpin, SIGNAL( valueChanged(double)), SLOT( onStepChange() ));
208 void GridAxisTab::onInsert()
210 if ( isGridBySpacing() )
212 QTreeWidgetItem * item = mySpacingTreeWdg->currentItem();
213 if ( !item ) item = mySpacingTreeWdg->topLevelItem( 0 );
214 int i = mySpacingTreeWdg->indexOfTopLevelItem( item );
216 double t0, t1; QString fun;
217 getFromItem( item, t0, t1, fun );
218 double t = 0.5 * ( t0 + t1 );
219 setToItem( t0, t, fun, item );
221 item = setToItem( t, t1, fun );
222 if ( i == mySpacingTreeWdg->topLevelItemCount()-1 )
223 mySpacingTreeWdg->addTopLevelItem( item );
225 mySpacingTreeWdg->insertTopLevelItem( i+1, item );
226 mySpacingTreeWdg->setCurrentItem( item );
230 if ( myCoordList->count() == 0 )
232 myCoordList->addItem( coordToItem( 0 ));
236 double coord = coordFromItem( myCoordList->currentItem() ) + myStep;
237 int i = myCoordList->currentRow();
238 while ( i > 0 && coordFromItem( myCoordList->item( i-1 )) > coord )
240 while ( i < myCoordList->count() && coordFromItem( myCoordList->item( i )) < coord )
242 const double tol = 1e-6;
244 ( i < myCoordList->count() && coordFromItem( myCoordList->item( i )) - coord < tol ) ||
245 ( i > 0 && coord - coordFromItem( myCoordList->item( i-1 )) < tol );
247 myCoordList->insertItem( i, coordToItem( coord ));
248 else if ( myStep < 0 )
250 myCoordList->setCurrentRow( i );
256 void GridAxisTab::onDelete()
258 if ( isGridBySpacing() )
260 QList<QTreeWidgetItem *> selItems = mySpacingTreeWdg->selectedItems();
261 QTreeWidgetItem * item;
262 foreach ( item, selItems )
264 int i = mySpacingTreeWdg->indexOfTopLevelItem( item );
265 if ( i == 0 ) continue;
266 QTreeWidgetItem* prevItem = mySpacingTreeWdg->topLevelItem( i-1 );
268 double t0, t1, t2; QString fun;
269 getFromItem( item, t1, t2, fun );
270 getFromItem( prevItem, t0, t1, fun );
273 setToItem( t0, t2, fun, prevItem );
278 if ( myCoordList->count() > 2 )
279 if ( QListWidgetItem * item = myCoordList->currentItem() )
285 void GridAxisTab::onMode(int isSpacing)
287 mySpacingTreeWdg->setShown( isSpacing );
288 myCoordList->setShown( !isSpacing );
289 myStepSpin->setShown( !isSpacing );
290 myStepLabel->setShown( !isSpacing );
293 if ( mySpacingTreeWdg->topLevelItemCount() == 0 )
295 QString spacing( "1" );
296 if ( myCoordList->count() > 1 )
298 double c1 = coordFromItem( myCoordList->item( 1 ));
299 double c0 = coordFromItem( myCoordList->item( 0 ));
300 spacing = QString::number( c1 - c0 );
302 mySpacingTreeWdg->addTopLevelItem( setToItem( 0., 1., spacing ) );
304 //myCoordList->clear();
308 //mySpacingTreeWdg->clear();
309 if ( myCoordList->count() == 0 )
310 myCoordList->addItem( coordToItem( 0 ));
315 void GridAxisTab::onStepChange()
317 if ( fabs( myStepSpin->GetValue() ) < 1e-100 )
319 double delta = myStepSpin->singleStep() * ( myStep > myStepSpin->GetValue() ? -1 : +1 );
320 myStepSpin->SetValue( myStepSpin->GetValue() + delta );
322 myStep = myStepSpin->GetValue();
325 void GridAxisTab::updateButtons()
327 bool insertEnable = false, deleteEnable = false;
328 if ( isGridBySpacing() )
331 const int nbSelected = mySpacingTreeWdg->selectedItems().count();
332 if ( nbSelected > 0 )
334 // we delete a current range by uniting it with the previous
335 int i = mySpacingTreeWdg->indexOfTopLevelItem( mySpacingTreeWdg->currentItem() );
336 deleteEnable = ( i > 0 );
341 const int nbSelected = myCoordList->selectedItems().count();
342 insertEnable = ( nbSelected || myCoordList->count() < 2 );
343 deleteEnable = ( nbSelected && myCoordList->count() > 2 );
345 myInsertBtn->setEnabled( insertEnable );
346 myDeleteBtn->setEnabled( deleteEnable );
349 void GridAxisTab::setCoordinates( SMESH::double_array_var coords )
351 myCoordList->clear();
352 for ( size_t i = 0; i < coords->length(); ++i )
353 myCoordList->addItem( coordToItem( coords[i] ));
355 myModeGroup->button( COORD_BUT )->setChecked( true );
359 void GridAxisTab::setSpacing( SMESH::string_array_var funs, SMESH::double_array_var points )
361 mySpacingTreeWdg->clear();
362 if ( funs->length() == points->length() - 1 )
364 for ( size_t i = 1; i < points->length(); ++i )
365 mySpacingTreeWdg->addTopLevelItem
366 ( setToItem( points[i-1], points[i], (const char*) funs[i-1] ));
368 myModeGroup->button( SPACING_BUT )->setChecked( true );
369 onMode( SPACING_BUT );
372 bool GridAxisTab::isGridBySpacing() const
374 return ( myModeGroup->checkedId() == SPACING_BUT );
377 SMESH::double_array* GridAxisTab::getCoordinates()
379 SMESH::double_array_var coords = new SMESH::double_array;
380 coords->length( myCoordList->count() );
381 for ( size_t i = 0; i < coords->length(); ++i )
382 coords[i] = coordFromItem( myCoordList->item( i ) );
384 return coords._retn();
387 void GridAxisTab::getSpacing(SMESH::string_array_out funs,
388 SMESH::double_array_out points) const
390 funs = new SMESH::string_array();
391 points = new SMESH::double_array();
392 funs->length( mySpacingTreeWdg->topLevelItemCount() );
393 points->length( mySpacingTreeWdg->topLevelItemCount() + 1 );
394 double t0, t1; QString fun;
395 for ( size_t i = 0; i < funs->length(); ++i )
397 QTreeWidgetItem* item = mySpacingTreeWdg->topLevelItem( i );
398 getFromItem( item, t0, t1, fun );
400 funs[i] = fun.toLatin1().constData();
402 points[ points->length()-1 ] = 1.0;
406 bool GridAxisTab::checkParams(QString& msg, SMESH::SMESH_Hypothesis_var& hyp) const
408 if ( isGridBySpacing() )
410 if ( mySpacingTreeWdg->topLevelItemCount() == 0 )
411 return false; // how could it be?
412 StdMeshers::StdMeshers_CartesianParameters3D_var h =
413 StdMeshers::StdMeshers_CartesianParameters3D::_narrow( hyp );
414 SMESH::string_array_var funs;
415 SMESH::double_array_var points;
416 getSpacing( funs.out(), points.out() );
418 const char* axisName[3] = { "X", "Y", "Z" };
419 SMESH::double_array_var coords =
420 h->ComputeCoordinates(0.,1., funs, points, axisName[ myAxisIndex ]);
422 catch ( const SALOME::SALOME_Exception& ex ) {
423 msg = (const char*) ex.details.text;
429 return myCoordList->count() > 1;
434 LineDelegate::LineDelegate( QWidget* parent ):
435 QItemDelegate( parent ),
436 mySpacingTreeWdg( qobject_cast<QTreeWidget*>( parent )),
437 myCoordList( qobject_cast<QListWidget*>( parent ))
441 QWidget* LineDelegate::createEditor( QWidget* parent,
442 const QStyleOptionViewItem& opt,
443 const QModelIndex& index) const
446 if ( mySpacingTreeWdg )
448 if ( index.column() == 0 &&
449 index.row() != mySpacingTreeWdg->topLevelItemCount()-1 )
451 SMESHGUI_SpinBox* sb = new SMESHGUI_SpinBox( parent );
452 sb->setAcceptNames( false ); // No Notebook variables allowed
453 sb->setFrame( false );
456 if ( index.column() == 1 ) {
457 w = new QLineEdit( parent );
462 SMESHGUI_SpinBox* sb = new SMESHGUI_SpinBox( parent );
463 sb->setAcceptNames( false ); // No Notebook variables allowed
464 sb->setFrame( false );
465 const double tol = 1e-5;
466 double from = index.row() ? coordFromItem( myCoordList->item( index.row()-1 ))+tol : -1e+6;
467 double to = index.row() == myCoordList->count()-1 ? 1e+6 : coordFromItem( myCoordList->item( index.row()+1 ))-tol;
468 sb->RangeStepAndValidator( from, to, 0.01 );
474 void LineDelegate::setEditorData ( QWidget * editor, const QModelIndex & index ) const
476 if ( mySpacingTreeWdg && index.column() == 0 )
478 double t0, t1, t2=1.0; QString fun;
479 QTreeWidgetItem* item = mySpacingTreeWdg->topLevelItem( index.row() );
480 getFromItem( item, t0, t1, fun );
481 if ( index.row() != mySpacingTreeWdg->topLevelItemCount()-1 )
483 item = mySpacingTreeWdg->topLevelItem( index.row()+1 );
484 getFromItem( item, t1, t2, fun );
486 const double tol = 1e-3;
487 SMESHGUI_SpinBox* sb = qobject_cast<SMESHGUI_SpinBox*>( editor );
488 sb->RangeStepAndValidator( t0 + tol, t2 - tol, 0.01 );
493 QItemDelegate::setEditorData( editor, index );
496 void LineDelegate::setModelData( QWidget* editor,
497 QAbstractItemModel* model,
498 const QModelIndex& index ) const
500 if ( mySpacingTreeWdg )
502 if ( index.column() == 0 )
504 if ( index.row() != mySpacingTreeWdg->topLevelItemCount()-1 )
506 SMESHGUI_SpinBox* sb = qobject_cast<SMESHGUI_SpinBox*>( editor );
507 double t0, t1, t = sb->GetValue(); QString fun;
509 QTreeWidgetItem* item = mySpacingTreeWdg->topLevelItem( index.row() );
510 getFromItem( item, t0, t1, fun );
511 setToItem( t0, t, fun, item );
513 item = mySpacingTreeWdg->topLevelItem( index.row() + 1 );
514 getFromItem( item, t0, t1, fun );
515 setToItem( t, t1, fun, item );
518 else if ( !qobject_cast<QLineEdit*>(editor)->text().trimmed().isEmpty() )
520 QItemDelegate::setModelData( editor, model, index );
525 SMESHGUI_SpinBox* sb = qobject_cast<SMESHGUI_SpinBox*>( editor );
526 coordToItem( sb->GetValue(), myCoordList->item( index.row() ));
530 } // namespace StdMeshersGUI
533 StdMeshersGUI_CartesianParamCreator::StdMeshersGUI_CartesianParamCreator(const QString& aHypType)
534 : StdMeshersGUI_StdHypothesisCreator( aHypType ),
542 StdMeshersGUI_CartesianParamCreator::~StdMeshersGUI_CartesianParamCreator()
544 if ( myAxisTabs[0] ) delete myAxisTabs[0];
545 if ( myAxisTabs[1] ) delete myAxisTabs[1];
546 if ( myAxisTabs[2] ) delete myAxisTabs[2];
552 bool StdMeshersGUI_CartesianParamCreator::checkParams( QString& msg ) const
554 if( !SMESHGUI_GenericHypothesisCreator::checkParams( msg ) )
557 if ( myName && myName->text().trimmed().isEmpty() )
559 msg = tr("SMESH_WRN_EMPTY_NAME");
562 if ( ! myThreshold->isValid( msg, true ))
565 SMESH::SMESH_Hypothesis_var hyp = hypothesis();
566 if ( !myAxisTabs[0]->checkParams( msg, hyp )) return false;
567 if ( !myAxisTabs[1]->checkParams( msg, hyp )) return false;
568 if ( !myAxisTabs[2]->checkParams( msg, hyp )) return false;
573 QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame()
575 QFrame* fr = new QFrame();
576 //fr->setMinimumWidth(460);
578 QVBoxLayout* lay = new QVBoxLayout( fr );
580 lay->setSpacing( SPACING );
582 QGroupBox* GroupC1 = new QGroupBox( tr( "SMESH_ARGUMENTS" ), fr );
583 lay->addWidget( GroupC1 );
585 StdMeshers::StdMeshers_NumberOfSegments_var h =
586 StdMeshers::StdMeshers_NumberOfSegments::_narrow( hypothesis() );
588 QGridLayout* argGroupLayout = new QGridLayout( GroupC1 );
589 argGroupLayout->setSpacing( SPACING );
590 argGroupLayout->setMargin( MARGIN );
591 argGroupLayout->setColumnStretch( 0, 0 );
592 argGroupLayout->setColumnStretch( 1, 1 );
599 myName = new QLineEdit( GroupC1 );
600 argGroupLayout->addWidget( new QLabel( tr( "SMESH_NAME" ), GroupC1 ), row, 0 );
601 argGroupLayout->addWidget( myName, row, 1 );
606 argGroupLayout->addWidget( new QLabel( tr( "THRESHOLD" ), GroupC1 ), row, 0 );
607 myThreshold = new SMESHGUI_SpinBox( GroupC1 );
608 myThreshold->setAcceptNames( false ); // No Notebook variables allowed
609 myThreshold->RangeStepAndValidator( 1.1, 1e+10, 1., "length_precision" );
610 argGroupLayout->addWidget( myThreshold, row, 1 );
613 // 2) Grid definition
614 QTabWidget* tabWdg = new QTabWidget( fr );
615 myAxisTabs[ 0 ] = new StdMeshersGUI::GridAxisTab( tabWdg, 0 );
616 myAxisTabs[ 1 ] = new StdMeshersGUI::GridAxisTab( tabWdg, 1 );
617 myAxisTabs[ 2 ] = new StdMeshersGUI::GridAxisTab( tabWdg, 2 );
618 tabWdg->addTab( myAxisTabs[ 0 ], tr( "AXIS_X" ) );
619 tabWdg->addTab( myAxisTabs[ 1 ], tr( "AXIS_Y" ) );
620 tabWdg->addTab( myAxisTabs[ 2 ], tr( "AXIS_Z" ) );
621 argGroupLayout->addWidget( tabWdg, row, 0, 1, 2 );
626 void StdMeshersGUI_CartesianParamCreator::retrieveParams() const
628 StdMeshers::StdMeshers_CartesianParameters3D_var h =
629 StdMeshers::StdMeshers_CartesianParameters3D::_narrow( initParamsHypothesis() );
632 myName->setText( hypName() );
634 QString varName = getVariableName( "SetSizeThreshold" );
635 if ( varName.isEmpty() )
636 myThreshold->setValue( h->GetSizeThreshold() );
638 myThreshold->setText( varName );
640 for ( int ax = 0; ax < 3; ++ax )
642 if ( h->IsGridBySpacing( ax ))
644 SMESH::string_array_var funs;
645 SMESH::double_array_var intPoints;
646 h->GetGridSpacing( funs.out(), intPoints.out(), ax );
647 myAxisTabs[ax]->setSpacing( funs, intPoints );
651 SMESH::double_array_var coords = h->GetGrid( ax );
652 myAxisTabs[ax]->setCoordinates( coords );
656 dlg()->setMinimumSize( dlg()->minimumSizeHint().width(), dlg()->minimumSizeHint().height() );
659 QString StdMeshersGUI_CartesianParamCreator::storeParams() const
661 StdMeshers::StdMeshers_CartesianParameters3D_var h =
662 StdMeshers::StdMeshers_CartesianParameters3D::_narrow( hypothesis() );
667 SMESH::SetName( SMESH::FindSObject( h ), myName->text().toLatin1().constData() );
669 h->SetVarParameter( myThreshold->text().toLatin1().constData(), "SetSizeThreshold" );
670 h->SetSizeThreshold( myThreshold->text().toDouble() );
672 for ( int ax = 0; ax < 3; ++ax )
674 if ( myAxisTabs[ax]->isGridBySpacing())
676 SMESH::double_array_var intPoints;
677 SMESH::string_array_var funs;
678 myAxisTabs[ax]->getSpacing( funs.out(), intPoints.out() );
679 h->SetGridSpacing( funs, intPoints, ax );
683 SMESH::double_array_var coords = myAxisTabs[ax]->getCoordinates();
684 h->SetGrid( coords, ax );
688 catch(const SALOME::SALOME_Exception& ex)
690 SalomeApp_Tools::QtCatchCorbaException(ex);
695 QString StdMeshersGUI_CartesianParamCreator::helpPage() const
697 return "cartesian_algo_page.html#cartesian_hyp_anchor";