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"
28 #include <SMESHGUI_SpinBox.h>
31 #include <QItemDelegate>
32 #include <QTableWidget>
33 #include <QPushButton>
34 #include <QVBoxLayout>
35 #include <QHBoxLayout>
40 \brief Sort list of points by ascending order.
43 static void sortData( QList<double>& d )
45 typedef QPair<double, double> Pair;
47 for ( int i = 0; i < d.count() / 2; i++ )
48 pairs.append( Pair( d[i*2], d[i*2+1] ) );
55 double prevX = 0.0, prevY = 0.0;
58 d.append( pairs.count() > 0 ? pairs[0].second : prevY );
61 if ( p.first > prevX ) {
76 \class StdMeshersGUI_DistrTableFrame::SpinBoxDelegate
77 \brief Custom item delegate (uses double spin box to edit table item)
81 class StdMeshersGUI_DistrTableFrame::SpinBoxDelegate : public QItemDelegate
84 SpinBoxDelegate( StdMeshersGUI_DistrTableFrame::Table* );
87 QWidget* createEditor( QWidget*,
88 const QStyleOptionViewItem&,
89 const QModelIndex& ) const;
90 void setEditorData( QWidget*, const QModelIndex&) const;
91 void setModelData( QWidget*, QAbstractItemModel*,
92 const QModelIndex& ) const;
93 void updateEditorGeometry( QWidget*,
94 const QStyleOptionViewItem&,
95 const QModelIndex& ) const;
98 StdMeshersGUI_DistrTableFrame::Table* myTable;
102 \class StdMeshersGUI_DistrTableFrame::Table
103 \brief Table function widget
107 class StdMeshersGUI_DistrTableFrame::Table : public QTableWidget
113 SMESHGUI_SpinBox* sb;
114 EditorData() { reset(); }
115 void reset() { r = -1; c = -1; sb = 0; }
119 Table( QWidget*, int = 2 );
122 QList<double> data();
123 void setData( const QList<double>& );
125 double value( int, int ) const;
126 void setValue( int, int, double );
128 double argMinimum( int ) const;
129 double argMaximum( int ) const;
130 double argStep( int ) const;
131 double funcMinimum( int ) const;
132 double funcMaximum( int ) const;
133 double funcStep( int ) const;
135 void setFuncMinValue( double );
137 QSize sizeHint() const;
142 void setEditor( int, int, SMESHGUI_SpinBox* );
145 void closeEditor( QWidget*, QAbstractItemDelegate::EndEditHint );
148 void setUpRows( bool = false );
149 QSize cachedSizeHint() const;
150 void setCachedSizeHint( const QSize& ) const;
151 QList<int> selectedRows();
155 QSize myCachedSizeHint;
156 EditorData myEditorData;
160 // StdMeshersGUI_DistrTableFrame::SpinBoxDelegate implementation
163 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
164 SpinBoxDelegate( StdMeshersGUI_DistrTableFrame::Table* parent )
165 : QItemDelegate( parent ), myTable( parent )
169 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
175 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
176 createEditor( QWidget* parent,
177 const QStyleOptionViewItem& /*option*/,
178 const QModelIndex& index ) const
180 SMESHGUI_SpinBox* sb = new SMESHGUI_SpinBox( parent );
182 sb->setAcceptNames(false); // No Notebook variables allowed
183 double aMin = index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
184 myTable->argMinimum( index.row() ) :
185 myTable->funcMinimum( index.row() );
186 double aMax = index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
187 myTable->argMaximum( index.row() ) :
188 myTable->funcMaximum( index.row() );
189 double aStep = index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ?
190 myTable->argStep( index.row() ) :
191 myTable->funcStep( index.row() );
192 sb->RangeStepAndValidator( aMin, aMax, aStep, "parametric_precision" );
195 myTable->setEditor( index.row(), index.column(), sb );
200 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
201 setEditorData( QWidget* editor, const QModelIndex& index ) const
203 QString value = index.model()->data(index, Qt::DisplayRole).toString();
204 SMESHGUI_SpinBox* sb = static_cast<SMESHGUI_SpinBox*>(editor);
207 double v = value.toDouble( &bOk );
208 if ( !bOk ) v = sb->minimum();
214 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
215 setModelData( QWidget* editor, QAbstractItemModel* model,
216 const QModelIndex& index ) const
218 SMESHGUI_SpinBox* sb = static_cast<SMESHGUI_SpinBox*>(editor);
219 model->setData( index, QString::number( sb->value() ), Qt::DisplayRole );
223 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
224 updateEditorGeometry( QWidget* editor,
225 const QStyleOptionViewItem& option,
226 const QModelIndex& /*index*/ ) const
228 editor->setGeometry( option.rect );
232 // StdMeshersGUI_DistrTableFrame::Table implementation
235 StdMeshersGUI_DistrTableFrame::Table::
236 Table( QWidget* parent, int rows )
237 : QTableWidget( parent ), myFuncMin( 0.0 )
239 setItemDelegate( new StdMeshersGUI_DistrTableFrame::SpinBoxDelegate( this ) );
244 labs << "t" << "f(t)";
245 setHorizontalHeaderLabels( labs );
254 StdMeshersGUI_DistrTableFrame::Table::
255 setEditor( int r, int c, SMESHGUI_SpinBox* sb )
259 myEditorData.sb = sb;
262 StdMeshersGUI_DistrTableFrame::Table::
268 StdMeshersGUI_DistrTableFrame::Table::
271 closePersistentEditor( currentItem() );
274 for ( int r = 0; r < rowCount(); r++ ) {
275 d.append( value( r, ArgColumn ) );
276 d.append( value( r, FuncColumn ) );
282 StdMeshersGUI_DistrTableFrame::Table::
283 setData( const QList<double>& d )
285 closePersistentEditor( currentItem() );
287 setRowCount( d.count() / 2 );
288 for ( int r = 0; r < rowCount(); r++ ) {
289 setValue( r, ArgColumn, d[r*2] );
290 setValue( r, FuncColumn, d[r*2+1] );
295 StdMeshersGUI_DistrTableFrame::Table::
296 value( int r, int c ) const
298 if ( r < 0 || r > rowCount() || c < 0 || c > columnCount() || !item( r, c ) )
301 return item( r, c )->text().toDouble();
305 StdMeshersGUI_DistrTableFrame::Table::
306 setValue( int r, int c, double v )
308 if ( r < 0 || r > rowCount() || c < 0 || c > columnCount() )
311 if ( c == FuncColumn && v < funcMinimum( r ) )
312 v = funcMinimum( r ); // correct func value according to the valid min value
313 if ( c == FuncColumn && v > funcMaximum( r ) )
314 v = funcMaximum( r ); // correct func value according to the valid max value
315 else if ( r == ArgColumn && v < argMinimum( r ) )
316 v = argMinimum( r ); // correct arg value according to the valid min value
317 else if ( r == ArgColumn && v > argMaximum( r ) )
318 v = argMaximum( r ); // correct arg value according to the valid max value
321 setItem( r, c, new QTableWidgetItem );
322 item( r, c )->setText( QString::number( v ) );
326 StdMeshersGUI_DistrTableFrame::Table::
327 argMinimum( int r ) const
329 // for the first row the minimum value is always 0.0
330 // for the other rows the minumum value is the above row's value
332 if ( r > 0 && r < rowCount() )
333 val = value( r-1, ArgColumn );
338 StdMeshersGUI_DistrTableFrame::Table::
339 argMaximum( int r ) const
341 // for the last row the maximum value is always 1.0
342 // for the other rows the maxumum value is the below row's value
344 if ( r >= 0 && r < rowCount()-1 ) {
345 val = value( r+1, ArgColumn );
351 StdMeshersGUI_DistrTableFrame::Table::
352 argStep( int /*r*/ ) const
354 // correct this to provide more smart behaviour if needed
359 StdMeshersGUI_DistrTableFrame::Table::
360 funcMinimum( int /*r*/ ) const
362 // correct this to provide more smart behaviour if needed
367 StdMeshersGUI_DistrTableFrame::Table::
368 funcMaximum( int /*r*/ ) const
370 // correct this to provide more smart behaviour if needed
375 StdMeshersGUI_DistrTableFrame::Table::
376 funcStep( int /*r*/ ) const
378 // correct this to provide more smart behaviour if needed
383 StdMeshersGUI_DistrTableFrame::Table::
384 setFuncMinValue( double val )
388 QTableWidgetItem* i = currentItem();
390 i->row() == myEditorData.r &&
391 i->column() == myEditorData.c &&
392 i->column() == FuncColumn &&
394 myEditorData.sb->setMinimum( myFuncMin );
397 closePersistentEditor( currentItem() );
400 for ( int r = 0; r < rowCount(); r++ ) {
401 double v = item( r, FuncColumn )->text().toDouble();
403 item( r, FuncColumn )->setText( QString::number( myFuncMin ) );
408 StdMeshersGUI_DistrTableFrame::Table::
411 if( cachedSizeHint().isValid() )
412 return cachedSizeHint();
414 QSize sh = QTableWidget::sizeHint();
415 if( sh.width() < 400 )
417 if( sh.height() < 200 )
420 setCachedSizeHint( sh );
425 StdMeshersGUI_DistrTableFrame::Table::
428 int r = currentRow() >= 0 ? currentRow() : ( rowCount() > 0 ? rowCount() - 1 : 0 );
431 double argMin = argMinimum( r );
432 double funcMin = funcMinimum( r );
434 setItem( r, ArgColumn, new QTableWidgetItem( QString::number( argMin ) ) );
435 setItem( r, FuncColumn, new QTableWidgetItem( QString::number( funcMin ) ) );
439 StdMeshersGUI_DistrTableFrame::Table::
442 QList<int> selRows = selectedRows();
443 for ( int r = selRows.count()-1; r >= 0; r-- )
448 StdMeshersGUI_DistrTableFrame::Table::
449 closeEditor( QWidget* editor, QAbstractItemDelegate::EndEditHint hint )
451 myEditorData.reset();
452 QTableWidget::closeEditor( editor, hint );
456 StdMeshersGUI_DistrTableFrame::Table::
457 setUpRows( bool autoset )
459 if ( rowCount() < 1 )
462 double s = argMaximum( rowCount()-1 ) / rowCount();
463 for ( int r = 0; r < rowCount()-1; r++ )
464 setValue( r, ArgColumn, r * s );
465 setValue( rowCount()-1, ArgColumn, argMaximum( rowCount()-1 ) );
473 StdMeshersGUI_DistrTableFrame::Table::
474 cachedSizeHint() const
476 return myCachedSizeHint;
480 StdMeshersGUI_DistrTableFrame::Table::
481 setCachedSizeHint( const QSize& s ) const
483 Table* that = const_cast<Table*>( this );
484 that->myCachedSizeHint = s;
488 StdMeshersGUI_DistrTableFrame::Table::
492 QList<QTableWidgetItem*> selItems = selectedItems();
494 foreach( i, selItems )
495 if ( !l.contains( i->row() ) ) l.append( i->row() );
501 \class StdMeshersGUI_DistrTableFrame
502 \brief Distribution table widget
505 StdMeshersGUI_DistrTableFrame::
506 StdMeshersGUI_DistrTableFrame( QWidget* parent )
509 QVBoxLayout* main = new QVBoxLayout( this );
510 main->setMargin( 0 );
511 main->setSpacing( 0 );
514 myTable = new Table( this );
515 connect( myTable, SIGNAL( valueChanged( int, int ) ), this, SIGNAL( valueChanged( int, int ) ) );
518 QWidget* aButFrame = new QWidget( this );
519 QHBoxLayout* butLay = new QHBoxLayout( aButFrame );
520 butLay->setContentsMargins( 0, SPACING, 0, SPACING );
521 butLay->setSpacing( SPACING );
523 myButtons[ InsertRowBtn ] = new QPushButton( tr( "SMESH_INSERT_ROW" ), aButFrame );
524 myButtons[ RemoveRowBtn ] = new QPushButton( tr( "SMESH_REMOVE_ROW" ), aButFrame );
526 butLay->addWidget( myButtons[ InsertRowBtn ] );
527 butLay->addWidget( myButtons[ RemoveRowBtn ] );
528 butLay->addStretch();
531 main->addWidget( myTable );
532 main->addWidget( aButFrame );
535 connect( myButtons[ InsertRowBtn ], SIGNAL( clicked() ), this, SLOT( onInsert() ) );
536 connect( myButtons[ RemoveRowBtn ], SIGNAL( clicked() ), this, SLOT( onRemove() ) );
537 connect( myTable, SIGNAL( currentCellChanged( int, int, int, int ) ),
538 this, SIGNAL( currentChanged( int, int ) ) );
539 connect( myTable, SIGNAL( cellChanged( int, int ) ),
540 this, SIGNAL( valueChanged( int, int ) ) );
543 StdMeshersGUI_DistrTableFrame::
544 ~StdMeshersGUI_DistrTableFrame()
549 StdMeshersGUI_DistrTableFrame::
550 showButton( const TableButton b, const bool on )
552 if ( button( b ) ) button( b )->setVisible( on );
556 StdMeshersGUI_DistrTableFrame::
557 isButtonShown( const TableButton b ) const
559 return button( b ) ? button( b )->isVisible() : false;
563 StdMeshersGUI_DistrTableFrame::
564 data( DataArray& array ) const
566 QList<double> d = myTable->data();
569 array.length( d.count() );
570 for ( int i = 0; i < d.count(); i++ )
575 StdMeshersGUI_DistrTableFrame::
576 setData( const DataArray& array )
579 for ( int i = 0; i < array.length(); i++ )
580 d.append( array[i] );
583 myTable->setData( d );
587 StdMeshersGUI_DistrTableFrame::
588 setFuncMinValue( double v )
590 myTable->setFuncMinValue( v );
594 StdMeshersGUI_DistrTableFrame::
595 button( const TableButton b ) const
597 return myButtons.contains( b ) ? myButtons[ b ] : 0;
601 StdMeshersGUI_DistrTableFrame::
608 StdMeshersGUI_DistrTableFrame::
611 myTable->deleteRow();