1 // Copyright (C) 2007-2010 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 <QPushButton>
35 #include <QVBoxLayout>
36 #include <QHBoxLayout>
41 \brief Sort list of points by ascending order.
44 static void sortData( QList<double>& d )
46 typedef QPair<double, double> Pair;
48 for ( int i = 0; i < d.count() / 2; i++ )
49 pairs.append( Pair( d[i*2], d[i*2+1] ) );
56 double prevX = 0.0, prevY = 0.0;
59 d.append( pairs.count() > 0 ? pairs[0].second : prevY );
62 if ( p.first > prevX ) {
77 \class StdMeshersGUI_DistrTableFrame::SpinBoxDelegate
78 \brief Custom item delegate (uses double spin box to edit table item)
82 class StdMeshersGUI_DistrTableFrame::SpinBoxDelegate : public QItemDelegate
85 SpinBoxDelegate( StdMeshersGUI_DistrTableFrame::Table* );
88 QWidget* createEditor( QWidget*,
89 const QStyleOptionViewItem&,
90 const QModelIndex& ) const;
91 void setEditorData( QWidget*, const QModelIndex&) const;
92 void setModelData( QWidget*, QAbstractItemModel*,
93 const QModelIndex& ) const;
94 void updateEditorGeometry( QWidget*,
95 const QStyleOptionViewItem&,
96 const QModelIndex& ) const;
99 StdMeshersGUI_DistrTableFrame::Table* myTable;
103 \class StdMeshersGUI_DistrTableFrame::Table
104 \brief Table function widget
108 class StdMeshersGUI_DistrTableFrame::Table : public QTableWidget
114 SMESHGUI_SpinBox* sb;
115 EditorData() { reset(); }
116 void reset() { r = -1; c = -1; sb = 0; }
120 Table( QWidget*, int = 2 );
123 QList<double> data();
124 void setData( const QList<double>& );
126 double value( int, int ) const;
127 void setValue( int, int, double );
129 double argMinimum( int ) const;
130 double argMaximum( int ) const;
131 double argStep( int ) const;
132 double funcMinimum( int ) const;
133 double funcMaximum( int ) const;
134 double funcStep( int ) const;
136 void setFuncMinValue( double );
138 QSize sizeHint() const;
143 void setEditor( int, int, SMESHGUI_SpinBox* );
146 void closeEditor( QWidget*, QAbstractItemDelegate::EndEditHint );
149 void setUpRows( bool = false );
150 QSize cachedSizeHint() const;
151 void setCachedSizeHint( const QSize& ) const;
152 QList<int> selectedRows();
156 QSize myCachedSizeHint;
157 EditorData myEditorData;
161 // StdMeshersGUI_DistrTableFrame::SpinBoxDelegate implementation
164 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
165 SpinBoxDelegate( StdMeshersGUI_DistrTableFrame::Table* parent )
166 : QItemDelegate( parent ), myTable( parent )
170 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
176 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
177 createEditor( QWidget* parent,
178 const QStyleOptionViewItem& /*option*/,
179 const QModelIndex& index ) const
181 SMESHGUI_SpinBox* sb = new SMESHGUI_SpinBox( parent );
183 sb->setAcceptNames(false); // No Notebook variables allowed
184 double aMin = index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
185 myTable->argMinimum( index.row() ) :
186 myTable->funcMinimum( index.row() );
187 double aMax = index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
188 myTable->argMaximum( index.row() ) :
189 myTable->funcMaximum( index.row() );
190 double aStep = index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
191 myTable->argStep( index.row() ) :
192 myTable->funcStep( index.row() );
193 sb->RangeStepAndValidator( aMin, aMax, aStep, "parametric_precision" );
196 myTable->setEditor( index.row(), index.column(), sb );
201 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
202 setEditorData( QWidget* editor, const QModelIndex& index ) const
204 QString value = index.model()->data(index, Qt::DisplayRole).toString();
205 SMESHGUI_SpinBox* sb = static_cast<SMESHGUI_SpinBox*>(editor);
208 double v = value.toDouble( &bOk );
209 if ( !bOk ) v = sb->minimum();
215 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
216 setModelData( QWidget* editor, QAbstractItemModel* model,
217 const QModelIndex& index ) const
219 SMESHGUI_SpinBox* sb = static_cast<SMESHGUI_SpinBox*>(editor);
220 model->setData( index, QString::number( sb->value() ), Qt::DisplayRole );
224 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
225 updateEditorGeometry( QWidget* editor,
226 const QStyleOptionViewItem& option,
227 const QModelIndex& /*index*/ ) const
229 editor->setGeometry( option.rect );
233 // StdMeshersGUI_DistrTableFrame::Table implementation
236 StdMeshersGUI_DistrTableFrame::Table::
237 Table( QWidget* parent, int rows )
238 : QTableWidget( parent ), myFuncMin( 0.0 )
240 setItemDelegate( new StdMeshersGUI_DistrTableFrame::SpinBoxDelegate( this ) );
245 labs << "t" << "f(t)";
246 setHorizontalHeaderLabels( labs );
255 StdMeshersGUI_DistrTableFrame::Table::
256 setEditor( int r, int c, SMESHGUI_SpinBox* sb )
260 myEditorData.sb = sb;
263 StdMeshersGUI_DistrTableFrame::Table::
269 StdMeshersGUI_DistrTableFrame::Table::
272 closePersistentEditor( currentItem() );
275 for ( int r = 0; r < rowCount(); r++ ) {
276 d.append( value( r, ArgColumn ) );
277 d.append( value( r, FuncColumn ) );
283 StdMeshersGUI_DistrTableFrame::Table::
284 setData( const QList<double>& d )
286 closePersistentEditor( currentItem() );
288 setRowCount( d.count() / 2 );
289 for ( int r = 0; r < rowCount(); r++ ) {
290 setValue( r, ArgColumn, d[r*2] );
291 setValue( r, FuncColumn, d[r*2+1] );
296 StdMeshersGUI_DistrTableFrame::Table::
297 value( int r, int c ) const
299 if ( r < 0 || r > rowCount() || c < 0 || c > columnCount() || !item( r, c ) )
302 return item( r, c )->text().toDouble();
306 StdMeshersGUI_DistrTableFrame::Table::
307 setValue( int r, int c, double v )
309 if ( r < 0 || r > rowCount() || c < 0 || c > columnCount() )
312 if ( c == FuncColumn && v < funcMinimum( r ) )
313 v = funcMinimum( r ); // correct func value according to the valid min value
314 if ( c == FuncColumn && v > funcMaximum( r ) )
315 v = funcMaximum( r ); // correct func value according to the valid max value
316 else if ( r == ArgColumn && v < argMinimum( r ) )
317 v = argMinimum( r ); // correct arg value according to the valid min value
318 else if ( r == ArgColumn && v > argMaximum( r ) )
319 v = argMaximum( r ); // correct arg value according to the valid max value
322 setItem( r, c, new QTableWidgetItem );
323 item( r, c )->setText( QString::number( v ) );
327 StdMeshersGUI_DistrTableFrame::Table::
328 argMinimum( int r ) const
330 // for the first row the minimum value is always 0.0
331 // for the other rows the minumum value is the above row's value
333 if ( r > 0 && r < rowCount() )
334 val = value( r-1, ArgColumn );
339 StdMeshersGUI_DistrTableFrame::Table::
340 argMaximum( int r ) const
342 // for the last row the maximum value is always 1.0
343 // for the other rows the maxumum value is the below row's value
345 if ( r >= 0 && r < rowCount()-1 ) {
346 val = value( r+1, ArgColumn );
352 StdMeshersGUI_DistrTableFrame::Table::
353 argStep( int /*r*/ ) const
355 // correct this to provide more smart behaviour if needed
360 StdMeshersGUI_DistrTableFrame::Table::
361 funcMinimum( int /*r*/ ) const
363 // correct this to provide more smart behaviour if needed
368 StdMeshersGUI_DistrTableFrame::Table::
369 funcMaximum( int /*r*/ ) const
371 // correct this to provide more smart behaviour if needed
376 StdMeshersGUI_DistrTableFrame::Table::
377 funcStep( int /*r*/ ) const
379 // correct this to provide more smart behaviour if needed
384 StdMeshersGUI_DistrTableFrame::Table::
385 setFuncMinValue( double val )
389 QTableWidgetItem* i = currentItem();
391 i->row() == myEditorData.r &&
392 i->column() == myEditorData.c &&
393 i->column() == FuncColumn &&
395 myEditorData.sb->setMinimum( myFuncMin );
398 closePersistentEditor( currentItem() );
401 for ( int r = 0; r < rowCount(); r++ ) {
402 double v = item( r, FuncColumn )->text().toDouble();
404 item( r, FuncColumn )->setText( QString::number( myFuncMin ) );
409 StdMeshersGUI_DistrTableFrame::Table::
412 if( cachedSizeHint().isValid() )
413 return cachedSizeHint();
415 QSize sh = QTableWidget::sizeHint();
416 if( sh.width() < 400 )
418 if( sh.height() < 200 )
421 setCachedSizeHint( sh );
426 StdMeshersGUI_DistrTableFrame::Table::
429 int r = currentRow() >= 0 ? currentRow() : ( rowCount() > 0 ? rowCount() - 1 : 0 );
432 double argMin = argMinimum( r );
433 double funcMin = funcMinimum( r );
435 setItem( r, ArgColumn, new QTableWidgetItem( QString::number( argMin ) ) );
436 setItem( r, FuncColumn, new QTableWidgetItem( QString::number( funcMin ) ) );
440 StdMeshersGUI_DistrTableFrame::Table::
443 QList<int> selRows = selectedRows();
444 for ( int r = selRows.count()-1; r >= 0; r-- )
449 StdMeshersGUI_DistrTableFrame::Table::
450 closeEditor( QWidget* editor, QAbstractItemDelegate::EndEditHint hint )
452 myEditorData.reset();
453 QTableWidget::closeEditor( editor, hint );
457 StdMeshersGUI_DistrTableFrame::Table::
458 setUpRows( bool autoset )
460 if ( rowCount() < 1 )
463 double s = argMaximum( rowCount()-1 ) / rowCount();
464 for ( int r = 0; r < rowCount()-1; r++ )
465 setValue( r, ArgColumn, r * s );
466 setValue( rowCount()-1, ArgColumn, argMaximum( rowCount()-1 ) );
474 StdMeshersGUI_DistrTableFrame::Table::
475 cachedSizeHint() const
477 return myCachedSizeHint;
481 StdMeshersGUI_DistrTableFrame::Table::
482 setCachedSizeHint( const QSize& s ) const
484 Table* that = const_cast<Table*>( this );
485 that->myCachedSizeHint = s;
489 StdMeshersGUI_DistrTableFrame::Table::
493 QList<QTableWidgetItem*> selItems = selectedItems();
495 foreach( i, selItems )
496 if ( !l.contains( i->row() ) ) l.append( i->row() );
502 \class StdMeshersGUI_DistrTableFrame
503 \brief Distribution table widget
506 StdMeshersGUI_DistrTableFrame::
507 StdMeshersGUI_DistrTableFrame( QWidget* parent )
510 QVBoxLayout* main = new QVBoxLayout( this );
511 main->setMargin( 0 );
512 main->setSpacing( 0 );
515 myTable = new Table( this );
516 connect( myTable, SIGNAL( valueChanged( int, int ) ), this, SIGNAL( valueChanged( int, int ) ) );
519 QWidget* aButFrame = new QWidget( this );
520 QHBoxLayout* butLay = new QHBoxLayout( aButFrame );
521 butLay->setContentsMargins( 0, SPACING, 0, SPACING );
522 butLay->setSpacing( SPACING );
524 myButtons[ InsertRowBtn ] = new QPushButton( tr( "SMESH_INSERT_ROW" ), aButFrame );
525 myButtons[ RemoveRowBtn ] = new QPushButton( tr( "SMESH_REMOVE_ROW" ), aButFrame );
527 butLay->addWidget( myButtons[ InsertRowBtn ] );
528 butLay->addWidget( myButtons[ RemoveRowBtn ] );
529 butLay->addStretch();
532 main->addWidget( myTable );
533 main->addWidget( aButFrame );
536 connect( myButtons[ InsertRowBtn ], SIGNAL( clicked() ), this, SLOT( onInsert() ) );
537 connect( myButtons[ RemoveRowBtn ], SIGNAL( clicked() ), this, SLOT( onRemove() ) );
538 connect( myTable, SIGNAL( currentCellChanged( int, int, int, int ) ),
539 this, SIGNAL( currentChanged( int, int ) ) );
540 connect( myTable, SIGNAL( cellChanged( int, int ) ),
541 this, SIGNAL( valueChanged( int, int ) ) );
544 StdMeshersGUI_DistrTableFrame::
545 ~StdMeshersGUI_DistrTableFrame()
550 StdMeshersGUI_DistrTableFrame::
551 showButton( const TableButton b, const bool on )
553 if ( button( b ) ) button( b )->setVisible( on );
557 StdMeshersGUI_DistrTableFrame::
558 isButtonShown( const TableButton b ) const
560 return button( b ) ? button( b )->isVisible() : false;
564 StdMeshersGUI_DistrTableFrame::
565 data( DataArray& array ) const
567 QList<double> d = myTable->data();
570 array.length( d.count() );
571 for ( int i = 0; i < d.count(); i++ )
576 StdMeshersGUI_DistrTableFrame::
577 setData( const DataArray& array )
580 for ( int i = 0; i < array.length(); i++ )
581 d.append( array[i] );
584 myTable->setData( d );
588 StdMeshersGUI_DistrTableFrame::
589 setFuncMinValue( double v )
591 myTable->setFuncMinValue( v );
595 StdMeshersGUI_DistrTableFrame::
596 button( const TableButton b ) const
598 return myButtons.contains( b ) ? myButtons[ b ] : 0;
602 StdMeshersGUI_DistrTableFrame::
609 StdMeshersGUI_DistrTableFrame::
612 myTable->deleteRow();