1 // Copyright (C) 2007-2011 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
23 // File : StdMeshersGUI_DistrTable.cxx
24 // Author : Open CASCADE S.A.S.
27 #include "StdMeshersGUI_DistrTable.h"
29 #include <SMESHGUI_SpinBox.h>
32 #include <QItemDelegate>
33 #include <QTableWidget>
34 #include <QHeaderView>
35 #include <QPushButton>
36 #include <QVBoxLayout>
37 #include <QHBoxLayout>
42 \brief Sort list of points by ascending order.
45 static void sortData( QList<double>& d )
47 typedef QPair<double, double> Pair;
49 for ( int i = 0; i < d.count() / 2; i++ )
50 pairs.append( Pair( d[i*2], d[i*2+1] ) );
57 double prevX = 0.0, prevY = 0.0;
60 d.append( pairs.count() > 0 ? pairs[0].second : prevY );
63 if ( p.first > prevX ) {
78 \class StdMeshersGUI_DistrTableFrame::SpinBoxDelegate
79 \brief Custom item delegate (uses double spin box to edit table item)
83 class StdMeshersGUI_DistrTableFrame::SpinBoxDelegate : public QItemDelegate
86 SpinBoxDelegate( StdMeshersGUI_DistrTableFrame::Table* );
89 QWidget* createEditor( QWidget*,
90 const QStyleOptionViewItem&,
91 const QModelIndex& ) const;
92 void setEditorData( QWidget*, const QModelIndex&) const;
93 void setModelData( QWidget*, QAbstractItemModel*,
94 const QModelIndex& ) const;
95 void updateEditorGeometry( QWidget*,
96 const QStyleOptionViewItem&,
97 const QModelIndex& ) const;
100 StdMeshersGUI_DistrTableFrame::Table* myTable;
104 \class StdMeshersGUI_DistrTableFrame::Table
105 \brief Table function widget
109 class StdMeshersGUI_DistrTableFrame::Table : public QTableWidget
115 SMESHGUI_SpinBox* sb;
116 EditorData() { reset(); }
117 void reset() { r = -1; c = -1; sb = 0; }
121 Table( QWidget*, int = 2 );
124 QList<double> data();
125 void setData( const QList<double>& );
127 double value( int, int ) const;
128 void setValue( int, int, double );
130 double argMinimum( int ) const;
131 double argMaximum( int ) const;
132 double argStep( int ) const;
133 double funcMinimum( int ) const;
134 double funcMaximum( int ) const;
135 double funcStep( int ) const;
137 void setFuncMinValue( double );
139 QSize sizeHint() const;
144 void setEditor( int, int, SMESHGUI_SpinBox* );
147 void closeEditor( QWidget*, QAbstractItemDelegate::EndEditHint );
150 void setUpRows( bool = false );
151 QSize cachedSizeHint() const;
152 void setCachedSizeHint( const QSize& ) const;
153 QList<int> selectedRows();
157 QSize myCachedSizeHint;
158 EditorData myEditorData;
162 // StdMeshersGUI_DistrTableFrame::SpinBoxDelegate implementation
165 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
166 SpinBoxDelegate( StdMeshersGUI_DistrTableFrame::Table* parent )
167 : QItemDelegate( parent ), myTable( parent )
171 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
177 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
178 createEditor( QWidget* parent,
179 const QStyleOptionViewItem& /*option*/,
180 const QModelIndex& index ) const
182 SMESHGUI_SpinBox* sb = new SMESHGUI_SpinBox( parent );
184 sb->setAcceptNames(false); // No Notebook variables allowed
185 double aMin = index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
186 myTable->argMinimum( index.row() ) :
187 myTable->funcMinimum( index.row() );
188 double aMax = index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
189 myTable->argMaximum( index.row() ) :
190 myTable->funcMaximum( index.row() );
191 double aStep = index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
192 myTable->argStep( index.row() ) :
193 myTable->funcStep( index.row() );
194 sb->RangeStepAndValidator( aMin, aMax, aStep, "parametric_precision" );
197 myTable->setEditor( index.row(), index.column(), sb );
202 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
203 setEditorData( QWidget* editor, const QModelIndex& index ) const
205 QString value = index.model()->data(index, Qt::DisplayRole).toString();
206 SMESHGUI_SpinBox* sb = static_cast<SMESHGUI_SpinBox*>(editor);
209 double v = value.toDouble( &bOk );
210 if ( !bOk ) v = sb->minimum();
216 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
217 setModelData( QWidget* editor, QAbstractItemModel* model,
218 const QModelIndex& index ) const
220 SMESHGUI_SpinBox* sb = static_cast<SMESHGUI_SpinBox*>(editor);
221 model->setData( index, QString::number( sb->value() ), Qt::DisplayRole );
225 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
226 updateEditorGeometry( QWidget* editor,
227 const QStyleOptionViewItem& option,
228 const QModelIndex& /*index*/ ) const
230 editor->setGeometry( option.rect );
234 // StdMeshersGUI_DistrTableFrame::Table implementation
237 StdMeshersGUI_DistrTableFrame::Table::
238 Table( QWidget* parent, int rows )
239 : QTableWidget( parent ), myFuncMin( 0.0 )
241 setItemDelegate( new StdMeshersGUI_DistrTableFrame::SpinBoxDelegate( this ) );
246 labs << "t" << "f(t)";
247 setHorizontalHeaderLabels( labs );
248 this->horizontalHeader()->setStretchLastSection(true);
249 this->horizontalHeader()->setDefaultSectionSize(60);
258 StdMeshersGUI_DistrTableFrame::Table::
259 setEditor( int r, int c, SMESHGUI_SpinBox* sb )
263 myEditorData.sb = sb;
266 StdMeshersGUI_DistrTableFrame::Table::
272 StdMeshersGUI_DistrTableFrame::Table::
275 closePersistentEditor( currentItem() );
278 for ( int r = 0; r < rowCount(); r++ ) {
279 d.append( value( r, ArgColumn ) );
280 d.append( value( r, FuncColumn ) );
286 StdMeshersGUI_DistrTableFrame::Table::
287 setData( const QList<double>& d )
289 closePersistentEditor( currentItem() );
291 setRowCount( d.count() / 2 );
292 for ( int r = 0; r < rowCount(); r++ ) {
293 setValue( r, ArgColumn, d[r*2] );
294 setValue( r, FuncColumn, d[r*2+1] );
299 StdMeshersGUI_DistrTableFrame::Table::
300 value( int r, int c ) const
302 if ( r < 0 || r > rowCount() || c < 0 || c > columnCount() || !item( r, c ) )
305 return item( r, c )->text().toDouble();
309 StdMeshersGUI_DistrTableFrame::Table::
310 setValue( int r, int c, double v )
312 if ( r < 0 || r > rowCount() || c < 0 || c > columnCount() )
315 if ( c == FuncColumn && v < funcMinimum( r ) )
316 v = funcMinimum( r ); // correct func value according to the valid min value
317 if ( c == FuncColumn && v > funcMaximum( r ) )
318 v = funcMaximum( r ); // correct func value according to the valid max value
319 else if ( r == ArgColumn && v < argMinimum( r ) )
320 v = argMinimum( r ); // correct arg value according to the valid min value
321 else if ( r == ArgColumn && v > argMaximum( r ) )
322 v = argMaximum( r ); // correct arg value according to the valid max value
325 setItem( r, c, new QTableWidgetItem );
326 item( r, c )->setText( QString::number( v ) );
330 StdMeshersGUI_DistrTableFrame::Table::
331 argMinimum( int r ) const
333 // for the first row the minimum value is always 0.0
334 // for the other rows the minumum value is the above row's value
336 if ( r > 0 && r < rowCount() )
337 val = value( r-1, ArgColumn );
342 StdMeshersGUI_DistrTableFrame::Table::
343 argMaximum( int r ) const
345 // for the last row the maximum value is always 1.0
346 // for the other rows the maxumum value is the below row's value
348 if ( r >= 0 && r < rowCount()-1 ) {
349 val = value( r+1, ArgColumn );
355 StdMeshersGUI_DistrTableFrame::Table::
356 argStep( int /*r*/ ) const
358 // correct this to provide more smart behaviour if needed
363 StdMeshersGUI_DistrTableFrame::Table::
364 funcMinimum( int /*r*/ ) const
366 // correct this to provide more smart behaviour if needed
371 StdMeshersGUI_DistrTableFrame::Table::
372 funcMaximum( int /*r*/ ) const
374 // correct this to provide more smart behaviour if needed
379 StdMeshersGUI_DistrTableFrame::Table::
380 funcStep( int /*r*/ ) const
382 // correct this to provide more smart behaviour if needed
387 StdMeshersGUI_DistrTableFrame::Table::
388 setFuncMinValue( double val )
392 QTableWidgetItem* i = currentItem();
394 i->row() == myEditorData.r &&
395 i->column() == myEditorData.c &&
396 i->column() == FuncColumn &&
398 myEditorData.sb->setMinimum( myFuncMin );
401 closePersistentEditor( currentItem() );
404 for ( int r = 0; r < rowCount(); r++ ) {
405 double v = item( r, FuncColumn )->text().toDouble();
407 item( r, FuncColumn )->setText( QString::number( myFuncMin ) );
412 StdMeshersGUI_DistrTableFrame::Table::
415 if( cachedSizeHint().isValid() )
416 return cachedSizeHint();
417 return QTableWidget::sizeHint();
418 // QSize sh = QTableWidget::sizeHint();
419 // if( sh.width() < 400 )
420 // sh.setWidth( 400 );
421 // if( sh.height() < 200 )
422 // sh.setHeight( 200 );
424 // setCachedSizeHint( sh );
429 StdMeshersGUI_DistrTableFrame::Table::
432 int r = currentRow() >= 0 ? currentRow() : ( rowCount() > 0 ? rowCount() - 1 : 0 );
435 double argMin = argMinimum( r );
436 double funcMin = funcMinimum( r );
438 setItem( r, ArgColumn, new QTableWidgetItem( QString::number( argMin ) ) );
439 setItem( r, FuncColumn, new QTableWidgetItem( QString::number( funcMin ) ) );
443 StdMeshersGUI_DistrTableFrame::Table::
446 QList<int> selRows = selectedRows();
447 for ( int r = selRows.count()-1; r >= 0; r-- )
452 StdMeshersGUI_DistrTableFrame::Table::
453 closeEditor( QWidget* editor, QAbstractItemDelegate::EndEditHint hint )
455 myEditorData.reset();
456 QTableWidget::closeEditor( editor, hint );
460 StdMeshersGUI_DistrTableFrame::Table::
461 setUpRows( bool autoset )
463 if ( rowCount() < 1 )
466 double s = argMaximum( rowCount()-1 ) / rowCount();
467 for ( int r = 0; r < rowCount()-1; r++ )
468 setValue( r, ArgColumn, r * s );
469 setValue( rowCount()-1, ArgColumn, argMaximum( rowCount()-1 ) );
477 StdMeshersGUI_DistrTableFrame::Table::
478 cachedSizeHint() const
480 return myCachedSizeHint;
484 StdMeshersGUI_DistrTableFrame::Table::
485 setCachedSizeHint( const QSize& s ) const
487 Table* that = const_cast<Table*>( this );
488 that->myCachedSizeHint = s;
492 StdMeshersGUI_DistrTableFrame::Table::
496 QList<QTableWidgetItem*> selItems = selectedItems();
498 foreach( i, selItems )
499 if ( !l.contains( i->row() ) ) l.append( i->row() );
505 \class StdMeshersGUI_DistrTableFrame
506 \brief Distribution table widget
509 StdMeshersGUI_DistrTableFrame::
510 StdMeshersGUI_DistrTableFrame( QWidget* parent )
513 QGridLayout* main = new QGridLayout( this );
514 main->setMargin( 0 );
515 main->setSpacing( 0 );
518 myTable = new Table( this );
519 connect( myTable, SIGNAL( valueChanged( int, int ) ), this, SIGNAL( valueChanged( int, int ) ) );
521 myButtons[ InsertRowBtn ] = new QPushButton( tr( "SMESH_INSERT_ROW" ), this );
522 myButtons[ RemoveRowBtn ] = new QPushButton( tr( "SMESH_REMOVE_ROW" ), this );
526 main->addWidget( myTable , 0, 0, 1, 3);
527 main->addWidget( myButtons[ InsertRowBtn ] , 1, 0);
528 main->addWidget( myButtons[ RemoveRowBtn ] , 1, 1);
529 main->setColumnStretch(2, 1);
530 main->setSpacing( SPACING );
533 connect( myButtons[ InsertRowBtn ], SIGNAL( clicked() ), this, SLOT( onInsert() ) );
534 connect( myButtons[ RemoveRowBtn ], SIGNAL( clicked() ), this, SLOT( onRemove() ) );
535 connect( myTable, SIGNAL( currentCellChanged( int, int, int, int ) ),
536 this, SIGNAL( currentChanged( int, int ) ) );
537 connect( myTable, SIGNAL( cellChanged( int, int ) ),
538 this, SIGNAL( valueChanged( int, int ) ) );
541 StdMeshersGUI_DistrTableFrame::
542 ~StdMeshersGUI_DistrTableFrame()
547 StdMeshersGUI_DistrTableFrame::
548 showButton( const TableButton b, const bool on )
550 if ( button( b ) ) button( b )->setVisible( on );
554 StdMeshersGUI_DistrTableFrame::
555 isButtonShown( const TableButton b ) const
557 return button( b ) ? button( b )->isVisible() : false;
561 StdMeshersGUI_DistrTableFrame::
562 data( DataArray& array ) const
564 QList<double> d = myTable->data();
567 array.length( d.count() );
568 for ( int i = 0; i < d.count(); i++ )
573 StdMeshersGUI_DistrTableFrame::
574 setData( const DataArray& array )
577 for ( int i = 0; i < array.length(); i++ )
578 d.append( array[i] );
581 myTable->setData( d );
585 StdMeshersGUI_DistrTableFrame::
586 setFuncMinValue( double v )
588 myTable->setFuncMinValue( v );
592 StdMeshersGUI_DistrTableFrame::
593 button( const TableButton b ) const
595 return myButtons.contains( b ) ? myButtons[ b ] : 0;
599 StdMeshersGUI_DistrTableFrame::
606 StdMeshersGUI_DistrTableFrame::
609 myTable->deleteRow();