1 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File : StdMeshersGUI_DistrTable.cxx
21 // Author : Open CASCADE S.A.S.
25 #include "StdMeshersGUI_DistrTable.h"
28 #include <QItemDelegate>
29 #include <QTableWidget>
30 #include <QDoubleSpinBox>
31 #include <QPushButton>
32 #include <QVBoxLayout>
33 #include <QHBoxLayout>
38 \brief Sort list of points by ascending order.
41 static void sortData( QList<double>& d )
43 typedef QPair<double, double> Pair;
45 for ( int i = 0; i < d.count() / 2; i++ )
46 pairs.append( Pair( d[i*2], d[i*2+1] ) );
53 double prevX = 0.0, prevY = 0.0;
56 d.append( pairs.count() > 0 ? pairs[0].second : prevY );
59 if ( p.first > prevX ) {
74 \class StdMeshersGUI_DistrTableFrame::SpinBoxDelegate
75 \brief Custom item delegate (uses double spin box to edit table item)
79 class StdMeshersGUI_DistrTableFrame::SpinBoxDelegate : public QItemDelegate
82 SpinBoxDelegate( StdMeshersGUI_DistrTableFrame::Table* );
85 QWidget* createEditor( QWidget*,
86 const QStyleOptionViewItem&,
87 const QModelIndex& ) const;
88 void setEditorData( QWidget*, const QModelIndex&) const;
89 void setModelData( QWidget*, QAbstractItemModel*,
90 const QModelIndex& ) const;
91 void updateEditorGeometry( QWidget*,
92 const QStyleOptionViewItem&,
93 const QModelIndex& ) const;
96 StdMeshersGUI_DistrTableFrame::Table* myTable;
100 \class StdMeshersGUI_DistrTableFrame::Table
101 \brief Table function widget
105 class StdMeshersGUI_DistrTableFrame::Table : public QTableWidget
112 EditorData() { reset(); }
113 void reset() { r = -1; c = -1; sb = 0; }
117 Table( QWidget*, int = 2 );
120 QList<double> data();
121 void setData( const QList<double>& );
123 double value( int, int ) const;
124 void setValue( int, int, double );
126 double argMinimum( int ) const;
127 double argMaximum( int ) const;
128 double argStep( int ) const;
129 double funcMinimum( int ) const;
130 double funcMaximum( int ) const;
131 double funcStep( int ) const;
133 void setFuncMinValue( double );
135 QSize sizeHint() const;
140 void setEditor( int, int, QDoubleSpinBox* );
143 void closeEditor( QWidget*, QAbstractItemDelegate::EndEditHint );
146 void setUpRows( bool = false );
147 QSize cachedSizeHint() const;
148 void setCachedSizeHint( const QSize& ) const;
149 QList<int> selectedRows();
153 QSize myCachedSizeHint;
154 EditorData myEditorData;
158 // StdMeshersGUI_DistrTableFrame::SpinBoxDelegate implementation
161 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
162 SpinBoxDelegate( StdMeshersGUI_DistrTableFrame::Table* parent )
163 : QItemDelegate( parent ), myTable( parent )
167 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
173 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
174 createEditor( QWidget* parent,
175 const QStyleOptionViewItem& /*option*/,
176 const QModelIndex& index ) const
178 QDoubleSpinBox* sb = new QDoubleSpinBox( parent );
180 sb->setMinimum( index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
181 myTable->argMinimum( index.row() ) :
182 myTable->funcMinimum( index.row() ) );
183 sb->setMaximum( index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
184 myTable->argMaximum( index.row() ) :
185 myTable->funcMaximum( index.row() ) );
186 sb->setSingleStep( index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
187 myTable->argStep( index.row() ) :
188 myTable->funcStep( index.row() ) );
189 myTable->setEditor( index.row(), index.column(), sb );
194 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
195 setEditorData( QWidget* editor, const QModelIndex& index ) const
197 QString value = index.model()->data(index, Qt::DisplayRole).toString();
198 QDoubleSpinBox* sb = static_cast<QDoubleSpinBox*>(editor);
201 double v = value.toDouble( &bOk );
202 if ( !bOk ) v = sb->minimum();
208 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
209 setModelData( QWidget* editor, QAbstractItemModel* model,
210 const QModelIndex& index ) const
212 QDoubleSpinBox* sb = static_cast<QDoubleSpinBox*>(editor);
213 model->setData( index, QString::number( sb->value() ), Qt::DisplayRole );
217 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
218 updateEditorGeometry( QWidget* editor,
219 const QStyleOptionViewItem& option,
220 const QModelIndex& /*index*/ ) const
222 editor->setGeometry( option.rect );
226 // StdMeshersGUI_DistrTableFrame::Table implementation
229 StdMeshersGUI_DistrTableFrame::Table::
230 Table( QWidget* parent, int rows )
231 : QTableWidget( parent ), myFuncMin( 0.0 )
233 setItemDelegate( new StdMeshersGUI_DistrTableFrame::SpinBoxDelegate( this ) );
238 labs << "t" << "f(t)";
239 setHorizontalHeaderLabels( labs );
248 StdMeshersGUI_DistrTableFrame::Table::
249 setEditor( int r, int c, QDoubleSpinBox* sb )
253 myEditorData.sb = sb;
256 StdMeshersGUI_DistrTableFrame::Table::
262 StdMeshersGUI_DistrTableFrame::Table::
265 closePersistentEditor( currentItem() );
268 for ( int r = 0; r < rowCount(); r++ ) {
269 d.append( value( r, ArgColumn ) );
270 d.append( value( r, FuncColumn ) );
276 StdMeshersGUI_DistrTableFrame::Table::
277 setData( const QList<double>& d )
279 closePersistentEditor( currentItem() );
281 setRowCount( d.count() / 2 );
282 for ( int r = 0; r < rowCount(); r++ ) {
283 setValue( r, ArgColumn, d[r*2] );
284 setValue( r, FuncColumn, d[r*2+1] );
289 StdMeshersGUI_DistrTableFrame::Table::
290 value( int r, int c ) const
292 if ( r < 0 || r > rowCount() || c < 0 || c > columnCount() || !item( r, c ) )
295 return item( r, c )->text().toDouble();
299 StdMeshersGUI_DistrTableFrame::Table::
300 setValue( int r, int c, double v )
302 if ( r < 0 || r > rowCount() || c < 0 || c > columnCount() )
305 if ( c == FuncColumn && v < funcMinimum( r ) )
306 v = funcMinimum( r ); // correct func value according to the valid min value
307 if ( c == FuncColumn && v < funcMaximum( r ) )
308 v = funcMaximum( r ); // correct func value according to the valid max value
309 else if ( r == ArgColumn && v < argMinimum( r ) )
310 v = argMinimum( r ); // correct arg value according to the valid min value
311 else if ( r == ArgColumn && v > argMaximum( r ) )
312 v = argMaximum( r ); // correct arg value according to the valid max value
315 setItem( r, c, new QTableWidgetItem );
316 item( r, c )->setText( QString::number( v ) );
320 StdMeshersGUI_DistrTableFrame::Table::
321 argMinimum( int r ) const
323 // for the first row the minimum value is always 0.0
324 // for the other rows the minumum value is the above row's value
326 if ( r > 0 && r < rowCount() )
327 val = value( r-1, ArgColumn );
332 StdMeshersGUI_DistrTableFrame::Table::
333 argMaximum( int r ) const
335 // for the last row the maximum value is always 1.0
336 // for the other rows the maxumum value is the below row's value
338 if ( r >= 0 && r < rowCount()-1 ) {
339 val = value( r+1, ArgColumn );
345 StdMeshersGUI_DistrTableFrame::Table::
346 argStep( int /*r*/ ) const
348 // correct this to provide more smart behaviour if needed
353 StdMeshersGUI_DistrTableFrame::Table::
354 funcMinimum( int /*r*/ ) const
356 // correct this to provide more smart behaviour if needed
361 StdMeshersGUI_DistrTableFrame::Table::
362 funcMaximum( int /*r*/ ) const
364 // correct this to provide more smart behaviour if needed
369 StdMeshersGUI_DistrTableFrame::Table::
370 funcStep( int /*r*/ ) const
372 // correct this to provide more smart behaviour if needed
377 StdMeshersGUI_DistrTableFrame::Table::
378 setFuncMinValue( double val )
382 QTableWidgetItem* i = currentItem();
384 i->row() == myEditorData.r &&
385 i->column() == myEditorData.c &&
386 i->column() == FuncColumn &&
388 myEditorData.sb->setMinimum( myFuncMin );
391 closePersistentEditor( currentItem() );
394 for ( int r = 0; r < rowCount(); r++ ) {
395 double v = item( r, FuncColumn )->text().toDouble();
397 item( r, FuncColumn )->setText( QString::number( myFuncMin ) );
402 StdMeshersGUI_DistrTableFrame::Table::
405 if( cachedSizeHint().isValid() )
406 return cachedSizeHint();
408 QSize sh = QTableWidget::sizeHint();
409 if( sh.width() < 400 )
411 if( sh.height() < 200 )
414 setCachedSizeHint( sh );
419 StdMeshersGUI_DistrTableFrame::Table::
422 int r = currentRow() >= 0 ? currentRow() : ( rowCount() > 0 ? rowCount() - 1 : 0 );
425 double argMin = argMinimum( r );
426 double funcMin = funcMinimum( r );
428 setItem( r, ArgColumn, new QTableWidgetItem( QString::number( argMin ) ) );
429 setItem( r, FuncColumn, new QTableWidgetItem( QString::number( funcMin ) ) );
433 StdMeshersGUI_DistrTableFrame::Table::
436 QList<int> selRows = selectedRows();
437 for ( int r = selRows.count()-1; r >= 0; r-- )
442 StdMeshersGUI_DistrTableFrame::Table::
443 closeEditor( QWidget* editor, QAbstractItemDelegate::EndEditHint hint )
445 myEditorData.reset();
446 QTableWidget::closeEditor( editor, hint );
450 StdMeshersGUI_DistrTableFrame::Table::
451 setUpRows( bool autoset )
453 if ( rowCount() < 1 )
456 double s = argMaximum( rowCount()-1 ) / rowCount();
457 for ( int r = 0; r < rowCount()-1; r++ )
458 setValue( r, ArgColumn, r * s );
459 setValue( rowCount()-1, ArgColumn, argMaximum( rowCount()-1 ) );
467 StdMeshersGUI_DistrTableFrame::Table::
468 cachedSizeHint() const
470 return myCachedSizeHint;
474 StdMeshersGUI_DistrTableFrame::Table::
475 setCachedSizeHint( const QSize& s ) const
477 Table* that = const_cast<Table*>( this );
478 that->myCachedSizeHint = s;
482 StdMeshersGUI_DistrTableFrame::Table::
486 QList<QTableWidgetItem*> selItems = selectedItems();
488 foreach( i, selItems )
489 if ( !l.contains( i->row() ) ) l.append( i->row() );
495 \class StdMeshersGUI_DistrTableFrame
496 \brief Distribution table widget
499 StdMeshersGUI_DistrTableFrame::
500 StdMeshersGUI_DistrTableFrame( QWidget* parent )
503 QVBoxLayout* main = new QVBoxLayout( this );
504 main->setMargin( 0 );
505 main->setSpacing( 0 );
508 myTable = new Table( this );
509 connect( myTable, SIGNAL( valueChanged( int, int ) ), this, SIGNAL( valueChanged( int, int ) ) );
512 QWidget* aButFrame = new QWidget( this );
513 QHBoxLayout* butLay = new QHBoxLayout( aButFrame );
514 butLay->setContentsMargins( 0, SPACING, 0, SPACING );
515 butLay->setSpacing( SPACING );
517 myButtons[ InsertRowBtn ] = new QPushButton( tr( "SMESH_INSERT_ROW" ), aButFrame );
518 myButtons[ RemoveRowBtn ] = new QPushButton( tr( "SMESH_REMOVE_ROW" ), aButFrame );
520 butLay->addWidget( myButtons[ InsertRowBtn ] );
521 butLay->addWidget( myButtons[ RemoveRowBtn ] );
522 butLay->addStretch();
525 main->addWidget( myTable );
526 main->addWidget( aButFrame );
529 connect( myButtons[ InsertRowBtn ], SIGNAL( clicked() ), this, SLOT( onInsert() ) );
530 connect( myButtons[ RemoveRowBtn ], SIGNAL( clicked() ), this, SLOT( onRemove() ) );
531 connect( myTable, SIGNAL( currentCellChanged( int, int, int, int ) ),
532 this, SIGNAL( currentChanged( int, int ) ) );
533 connect( myTable, SIGNAL( cellChanged( int, int ) ),
534 this, SIGNAL( valueChanged( int, int ) ) );
537 StdMeshersGUI_DistrTableFrame::
538 ~StdMeshersGUI_DistrTableFrame()
543 StdMeshersGUI_DistrTableFrame::
544 showButton( const TableButton b, const bool on )
546 if ( button( b ) ) button( b )->setVisible( on );
550 StdMeshersGUI_DistrTableFrame::
551 isButtonShown( const TableButton b ) const
553 return button( b ) ? button( b )->isVisible() : false;
557 StdMeshersGUI_DistrTableFrame::
558 data( DataArray& array ) const
560 QList<double> d = myTable->data();
563 array.length( d.count() );
564 for ( int i = 0; i < d.count(); i++ )
569 StdMeshersGUI_DistrTableFrame::
570 setData( const DataArray& array )
573 for ( int i = 0; i < array.length(); i++ )
574 d.append( array[i] );
577 myTable->setData( d );
581 StdMeshersGUI_DistrTableFrame::
582 setFuncMinValue( double v )
584 myTable->setFuncMinValue( v );
588 StdMeshersGUI_DistrTableFrame::
589 button( const TableButton b ) const
591 return myButtons.contains( b ) ? myButtons[ b ] : 0;
595 StdMeshersGUI_DistrTableFrame::
602 StdMeshersGUI_DistrTableFrame::
605 myTable->deleteRow();