1 // Copyright (C) 2007-2008 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_DistrTable.cxx
23 // Author : Open CASCADE S.A.S.
26 #include "StdMeshersGUI_DistrTable.h"
29 #include <QItemDelegate>
30 #include <QTableWidget>
31 #include <QDoubleSpinBox>
32 #include <QPushButton>
33 #include <QVBoxLayout>
34 #include <QHBoxLayout>
39 \brief Sort list of points by ascending order.
42 static void sortData( QList<double>& d )
44 typedef QPair<double, double> Pair;
46 for ( int i = 0; i < d.count() / 2; i++ )
47 pairs.append( Pair( d[i*2], d[i*2+1] ) );
54 double prevX = 0.0, prevY = 0.0;
57 d.append( pairs.count() > 0 ? pairs[0].second : prevY );
60 if ( p.first > prevX ) {
75 \class StdMeshersGUI_DistrTableFrame::SpinBoxDelegate
76 \brief Custom item delegate (uses double spin box to edit table item)
80 class StdMeshersGUI_DistrTableFrame::SpinBoxDelegate : public QItemDelegate
83 SpinBoxDelegate( StdMeshersGUI_DistrTableFrame::Table* );
86 QWidget* createEditor( QWidget*,
87 const QStyleOptionViewItem&,
88 const QModelIndex& ) const;
89 void setEditorData( QWidget*, const QModelIndex&) const;
90 void setModelData( QWidget*, QAbstractItemModel*,
91 const QModelIndex& ) const;
92 void updateEditorGeometry( QWidget*,
93 const QStyleOptionViewItem&,
94 const QModelIndex& ) const;
97 StdMeshersGUI_DistrTableFrame::Table* myTable;
101 \class StdMeshersGUI_DistrTableFrame::Table
102 \brief Table function widget
106 class StdMeshersGUI_DistrTableFrame::Table : public QTableWidget
113 EditorData() { reset(); }
114 void reset() { r = -1; c = -1; sb = 0; }
118 Table( QWidget*, int = 2 );
121 QList<double> data();
122 void setData( const QList<double>& );
124 double value( int, int ) const;
125 void setValue( int, int, double );
127 double argMinimum( int ) const;
128 double argMaximum( int ) const;
129 double argStep( int ) const;
130 double funcMinimum( int ) const;
131 double funcMaximum( int ) const;
132 double funcStep( int ) const;
134 void setFuncMinValue( double );
136 QSize sizeHint() const;
141 void setEditor( int, int, QDoubleSpinBox* );
144 void closeEditor( QWidget*, QAbstractItemDelegate::EndEditHint );
147 void setUpRows( bool = false );
148 QSize cachedSizeHint() const;
149 void setCachedSizeHint( const QSize& ) const;
150 QList<int> selectedRows();
154 QSize myCachedSizeHint;
155 EditorData myEditorData;
159 // StdMeshersGUI_DistrTableFrame::SpinBoxDelegate implementation
162 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
163 SpinBoxDelegate( StdMeshersGUI_DistrTableFrame::Table* parent )
164 : QItemDelegate( parent ), myTable( parent )
168 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
174 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
175 createEditor( QWidget* parent,
176 const QStyleOptionViewItem& /*option*/,
177 const QModelIndex& index ) const
179 QDoubleSpinBox* sb = new QDoubleSpinBox( parent );
181 sb->setMinimum( index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
182 myTable->argMinimum( index.row() ) :
183 myTable->funcMinimum( index.row() ) );
184 sb->setMaximum( index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
185 myTable->argMaximum( index.row() ) :
186 myTable->funcMaximum( index.row() ) );
187 sb->setSingleStep( index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
188 myTable->argStep( index.row() ) :
189 myTable->funcStep( index.row() ) );
190 myTable->setEditor( index.row(), index.column(), sb );
195 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
196 setEditorData( QWidget* editor, const QModelIndex& index ) const
198 QString value = index.model()->data(index, Qt::DisplayRole).toString();
199 QDoubleSpinBox* sb = static_cast<QDoubleSpinBox*>(editor);
202 double v = value.toDouble( &bOk );
203 if ( !bOk ) v = sb->minimum();
209 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
210 setModelData( QWidget* editor, QAbstractItemModel* model,
211 const QModelIndex& index ) const
213 QDoubleSpinBox* sb = static_cast<QDoubleSpinBox*>(editor);
214 model->setData( index, QString::number( sb->value() ), Qt::DisplayRole );
218 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
219 updateEditorGeometry( QWidget* editor,
220 const QStyleOptionViewItem& option,
221 const QModelIndex& /*index*/ ) const
223 editor->setGeometry( option.rect );
227 // StdMeshersGUI_DistrTableFrame::Table implementation
230 StdMeshersGUI_DistrTableFrame::Table::
231 Table( QWidget* parent, int rows )
232 : QTableWidget( parent ), myFuncMin( 0.0 )
234 setItemDelegate( new StdMeshersGUI_DistrTableFrame::SpinBoxDelegate( this ) );
239 labs << "t" << "f(t)";
240 setHorizontalHeaderLabels( labs );
249 StdMeshersGUI_DistrTableFrame::Table::
250 setEditor( int r, int c, QDoubleSpinBox* sb )
254 myEditorData.sb = sb;
257 StdMeshersGUI_DistrTableFrame::Table::
263 StdMeshersGUI_DistrTableFrame::Table::
266 closePersistentEditor( currentItem() );
269 for ( int r = 0; r < rowCount(); r++ ) {
270 d.append( value( r, ArgColumn ) );
271 d.append( value( r, FuncColumn ) );
277 StdMeshersGUI_DistrTableFrame::Table::
278 setData( const QList<double>& d )
280 closePersistentEditor( currentItem() );
282 setRowCount( d.count() / 2 );
283 for ( int r = 0; r < rowCount(); r++ ) {
284 setValue( r, ArgColumn, d[r*2] );
285 setValue( r, FuncColumn, d[r*2+1] );
290 StdMeshersGUI_DistrTableFrame::Table::
291 value( int r, int c ) const
293 if ( r < 0 || r > rowCount() || c < 0 || c > columnCount() || !item( r, c ) )
296 return item( r, c )->text().toDouble();
300 StdMeshersGUI_DistrTableFrame::Table::
301 setValue( int r, int c, double v )
303 if ( r < 0 || r > rowCount() || c < 0 || c > columnCount() )
306 if ( c == FuncColumn && v < funcMinimum( r ) )
307 v = funcMinimum( r ); // correct func value according to the valid min value
308 if ( c == FuncColumn && v > funcMaximum( r ) )
309 v = funcMaximum( r ); // correct func value according to the valid max value
310 else if ( r == ArgColumn && v < argMinimum( r ) )
311 v = argMinimum( r ); // correct arg value according to the valid min value
312 else if ( r == ArgColumn && v > argMaximum( r ) )
313 v = argMaximum( r ); // correct arg value according to the valid max value
316 setItem( r, c, new QTableWidgetItem );
317 item( r, c )->setText( QString::number( v ) );
321 StdMeshersGUI_DistrTableFrame::Table::
322 argMinimum( int r ) const
324 // for the first row the minimum value is always 0.0
325 // for the other rows the minumum value is the above row's value
327 if ( r > 0 && r < rowCount() )
328 val = value( r-1, ArgColumn );
333 StdMeshersGUI_DistrTableFrame::Table::
334 argMaximum( int r ) const
336 // for the last row the maximum value is always 1.0
337 // for the other rows the maxumum value is the below row's value
339 if ( r >= 0 && r < rowCount()-1 ) {
340 val = value( r+1, ArgColumn );
346 StdMeshersGUI_DistrTableFrame::Table::
347 argStep( int /*r*/ ) const
349 // correct this to provide more smart behaviour if needed
354 StdMeshersGUI_DistrTableFrame::Table::
355 funcMinimum( int /*r*/ ) const
357 // correct this to provide more smart behaviour if needed
362 StdMeshersGUI_DistrTableFrame::Table::
363 funcMaximum( int /*r*/ ) const
365 // correct this to provide more smart behaviour if needed
370 StdMeshersGUI_DistrTableFrame::Table::
371 funcStep( int /*r*/ ) const
373 // correct this to provide more smart behaviour if needed
378 StdMeshersGUI_DistrTableFrame::Table::
379 setFuncMinValue( double val )
383 QTableWidgetItem* i = currentItem();
385 i->row() == myEditorData.r &&
386 i->column() == myEditorData.c &&
387 i->column() == FuncColumn &&
389 myEditorData.sb->setMinimum( myFuncMin );
392 closePersistentEditor( currentItem() );
395 for ( int r = 0; r < rowCount(); r++ ) {
396 double v = item( r, FuncColumn )->text().toDouble();
398 item( r, FuncColumn )->setText( QString::number( myFuncMin ) );
403 StdMeshersGUI_DistrTableFrame::Table::
406 if( cachedSizeHint().isValid() )
407 return cachedSizeHint();
409 QSize sh = QTableWidget::sizeHint();
410 if( sh.width() < 400 )
412 if( sh.height() < 200 )
415 setCachedSizeHint( sh );
420 StdMeshersGUI_DistrTableFrame::Table::
423 int r = currentRow() >= 0 ? currentRow() : ( rowCount() > 0 ? rowCount() - 1 : 0 );
426 double argMin = argMinimum( r );
427 double funcMin = funcMinimum( r );
429 setItem( r, ArgColumn, new QTableWidgetItem( QString::number( argMin ) ) );
430 setItem( r, FuncColumn, new QTableWidgetItem( QString::number( funcMin ) ) );
434 StdMeshersGUI_DistrTableFrame::Table::
437 QList<int> selRows = selectedRows();
438 for ( int r = selRows.count()-1; r >= 0; r-- )
443 StdMeshersGUI_DistrTableFrame::Table::
444 closeEditor( QWidget* editor, QAbstractItemDelegate::EndEditHint hint )
446 myEditorData.reset();
447 QTableWidget::closeEditor( editor, hint );
451 StdMeshersGUI_DistrTableFrame::Table::
452 setUpRows( bool autoset )
454 if ( rowCount() < 1 )
457 double s = argMaximum( rowCount()-1 ) / rowCount();
458 for ( int r = 0; r < rowCount()-1; r++ )
459 setValue( r, ArgColumn, r * s );
460 setValue( rowCount()-1, ArgColumn, argMaximum( rowCount()-1 ) );
468 StdMeshersGUI_DistrTableFrame::Table::
469 cachedSizeHint() const
471 return myCachedSizeHint;
475 StdMeshersGUI_DistrTableFrame::Table::
476 setCachedSizeHint( const QSize& s ) const
478 Table* that = const_cast<Table*>( this );
479 that->myCachedSizeHint = s;
483 StdMeshersGUI_DistrTableFrame::Table::
487 QList<QTableWidgetItem*> selItems = selectedItems();
489 foreach( i, selItems )
490 if ( !l.contains( i->row() ) ) l.append( i->row() );
496 \class StdMeshersGUI_DistrTableFrame
497 \brief Distribution table widget
500 StdMeshersGUI_DistrTableFrame::
501 StdMeshersGUI_DistrTableFrame( QWidget* parent )
504 QVBoxLayout* main = new QVBoxLayout( this );
505 main->setMargin( 0 );
506 main->setSpacing( 0 );
509 myTable = new Table( this );
510 connect( myTable, SIGNAL( valueChanged( int, int ) ), this, SIGNAL( valueChanged( int, int ) ) );
513 QWidget* aButFrame = new QWidget( this );
514 QHBoxLayout* butLay = new QHBoxLayout( aButFrame );
515 butLay->setContentsMargins( 0, SPACING, 0, SPACING );
516 butLay->setSpacing( SPACING );
518 myButtons[ InsertRowBtn ] = new QPushButton( tr( "SMESH_INSERT_ROW" ), aButFrame );
519 myButtons[ RemoveRowBtn ] = new QPushButton( tr( "SMESH_REMOVE_ROW" ), aButFrame );
521 butLay->addWidget( myButtons[ InsertRowBtn ] );
522 butLay->addWidget( myButtons[ RemoveRowBtn ] );
523 butLay->addStretch();
526 main->addWidget( myTable );
527 main->addWidget( aButFrame );
530 connect( myButtons[ InsertRowBtn ], SIGNAL( clicked() ), this, SLOT( onInsert() ) );
531 connect( myButtons[ RemoveRowBtn ], SIGNAL( clicked() ), this, SLOT( onRemove() ) );
532 connect( myTable, SIGNAL( currentCellChanged( int, int, int, int ) ),
533 this, SIGNAL( currentChanged( int, int ) ) );
534 connect( myTable, SIGNAL( cellChanged( int, int ) ),
535 this, SIGNAL( valueChanged( int, int ) ) );
538 StdMeshersGUI_DistrTableFrame::
539 ~StdMeshersGUI_DistrTableFrame()
544 StdMeshersGUI_DistrTableFrame::
545 showButton( const TableButton b, const bool on )
547 if ( button( b ) ) button( b )->setVisible( on );
551 StdMeshersGUI_DistrTableFrame::
552 isButtonShown( const TableButton b ) const
554 return button( b ) ? button( b )->isVisible() : false;
558 StdMeshersGUI_DistrTableFrame::
559 data( DataArray& array ) const
561 QList<double> d = myTable->data();
564 array.length( d.count() );
565 for ( int i = 0; i < d.count(); i++ )
570 StdMeshersGUI_DistrTableFrame::
571 setData( const DataArray& array )
574 for ( int i = 0; i < array.length(); i++ )
575 d.append( array[i] );
578 myTable->setData( d );
582 StdMeshersGUI_DistrTableFrame::
583 setFuncMinValue( double v )
585 myTable->setFuncMinValue( v );
589 StdMeshersGUI_DistrTableFrame::
590 button( const TableButton b ) const
592 return myButtons.contains( b ) ? myButtons[ b ] : 0;
596 StdMeshersGUI_DistrTableFrame::
603 StdMeshersGUI_DistrTableFrame::
606 myTable->deleteRow();