Back to index

salome-smesh  6.5.0
StdMeshersGUI_DistrTable.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 // File   : StdMeshersGUI_DistrTable.cxx
00024 // Author : Open CASCADE S.A.S.
00025 // SMESH includes
00026 //
00027 #include "StdMeshersGUI_DistrTable.h"
00028 
00029 #include <SMESHGUI_SpinBox.h>
00030 
00031 // Qt incldues
00032 #include <QItemDelegate>
00033 #include <QTableWidget>
00034 #include <QHeaderView>
00035 #include <QPushButton>
00036 #include <QVBoxLayout>
00037 #include <QHBoxLayout>
00038 
00039 #define SPACING 6
00040 
00045 static void sortData( QList<double>& d )
00046 {
00047   typedef QPair<double, double> Pair;
00048   QList<Pair> pairs;
00049   for ( int i = 0; i < d.count() / 2; i++ )
00050     pairs.append( Pair( d[i*2], d[i*2+1] ) );
00051   
00052   qSort( pairs );
00053 
00054   d.clear();
00055 
00056   Pair p;
00057   double prevX = 0.0, prevY = 0.0;
00058 
00059   d.append( prevX );
00060   d.append( pairs.count() > 0 ? pairs[0].second : prevY );
00061 
00062   foreach( p, pairs ) {
00063     if ( p.first > prevX ) {
00064       d.append( p.first  );
00065       d.append( p.second );
00066       prevY = p.second;
00067     }
00068     prevX = p.first;
00069   }
00070 
00071   if ( prevX < 1.0 ) {
00072     d.append( 1.0 );
00073     d.append( prevY );
00074   }
00075 }
00076 
00083 class StdMeshersGUI_DistrTableFrame::SpinBoxDelegate : public QItemDelegate
00084 {
00085 public:
00086   SpinBoxDelegate( StdMeshersGUI_DistrTableFrame::Table* );
00087   ~SpinBoxDelegate();
00088 
00089   QWidget* createEditor( QWidget*,
00090                          const QStyleOptionViewItem&,
00091                          const QModelIndex& ) const;
00092   void     setEditorData( QWidget*, const QModelIndex&) const;
00093   void     setModelData( QWidget*, QAbstractItemModel*, 
00094                          const QModelIndex& ) const;
00095   void     updateEditorGeometry( QWidget*,
00096                                  const QStyleOptionViewItem&, 
00097                                  const QModelIndex& ) const;
00098 
00099 private:
00100   StdMeshersGUI_DistrTableFrame::Table* myTable;
00101 };
00102 
00109 class StdMeshersGUI_DistrTableFrame::Table : public QTableWidget
00110 {
00111 private:
00112   struct EditorData
00113   { 
00114     int r, c;
00115     SMESHGUI_SpinBox* sb;
00116     EditorData() { reset(); }
00117     void reset() { r = -1; c = -1; sb = 0; }
00118   };
00119 
00120 public:
00121   Table( QWidget*, int = 2 );
00122   ~Table();
00123 
00124   QList<double> data();
00125   void          setData( const QList<double>& );
00126 
00127   double        value( int, int ) const;
00128   void          setValue( int, int, double );
00129 
00130   double        argMinimum( int ) const;
00131   double        argMaximum( int ) const;
00132   double        argStep( int ) const;
00133   double        funcMinimum( int ) const;
00134   double        funcMaximum( int ) const;
00135   double        funcStep( int ) const;
00136 
00137   void          setFuncMinValue( double );
00138 
00139   QSize         sizeHint() const;
00140 
00141   void          addRow();
00142   void          deleteRow();
00143 
00144   void          setEditor( int, int, SMESHGUI_SpinBox* );
00145 
00146 protected:
00147   void          closeEditor( QWidget*, QAbstractItemDelegate::EndEditHint );
00148 
00149 private:
00150   void          setUpRows( bool = false );
00151   QSize         cachedSizeHint() const;
00152   void          setCachedSizeHint( const QSize& ) const;
00153   QList<int>    selectedRows();
00154 
00155 private:
00156   double        myFuncMin;
00157   QSize         myCachedSizeHint;
00158   EditorData    myEditorData;
00159 };
00160 
00161 // ---
00162 // StdMeshersGUI_DistrTableFrame::SpinBoxDelegate implementation
00163 // ---
00164 
00165 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
00166 SpinBoxDelegate( StdMeshersGUI_DistrTableFrame::Table* parent )
00167   : QItemDelegate( parent ), myTable( parent )
00168 {
00169 }
00170 
00171 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
00172 ~SpinBoxDelegate()
00173 {
00174 }
00175 
00176 QWidget* 
00177 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
00178 createEditor( QWidget* parent,
00179               const QStyleOptionViewItem& /*option*/,
00180               const QModelIndex& index ) const
00181 {
00182   SMESHGUI_SpinBox* sb = new SMESHGUI_SpinBox( parent );
00183   
00184   sb->setAcceptNames(false); // No Notebook variables allowed
00185   double aMin = index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ? 
00186                   myTable->argMinimum( index.row() ) : 
00187                   myTable->funcMinimum( index.row() );
00188   double aMax = index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ? 
00189                   myTable->argMaximum( index.row() ) : 
00190                   myTable->funcMaximum( index.row() );
00191   double aStep = index.column() == StdMeshersGUI_DistrTableFrame::ArgColumn ? 
00192                      myTable->argStep( index.row() ) : 
00193                      myTable->funcStep( index.row() );
00194   sb->RangeStepAndValidator( aMin, aMax, aStep, "parametric_precision" );
00195   sb->setFrame(false);
00196 
00197   myTable->setEditor( index.row(), index.column(), sb );  
00198   return sb;
00199 }
00200 
00201 void 
00202 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
00203 setEditorData( QWidget* editor, const QModelIndex& index ) const
00204 {
00205   QString value = index.model()->data(index, Qt::DisplayRole).toString();
00206   SMESHGUI_SpinBox* sb = static_cast<SMESHGUI_SpinBox*>(editor);
00207 
00208   bool bOk = false;
00209   double v = value.toDouble( &bOk );
00210   if ( !bOk ) v = sb->minimum();
00211 
00212   sb->setValue( v );
00213 }
00214 
00215 void
00216 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
00217 setModelData( QWidget* editor, QAbstractItemModel* model, 
00218               const QModelIndex& index ) const
00219 {
00220   SMESHGUI_SpinBox* sb = static_cast<SMESHGUI_SpinBox*>(editor);
00221   model->setData( index, QString::number( sb->value() ), Qt::DisplayRole );
00222 }
00223 
00224 void 
00225 StdMeshersGUI_DistrTableFrame::SpinBoxDelegate::
00226 updateEditorGeometry( QWidget* editor,
00227                       const QStyleOptionViewItem& option, 
00228                       const QModelIndex& /*index*/ ) const
00229 {
00230   editor->setGeometry( option.rect );
00231 }
00232 
00233 // ---
00234 // StdMeshersGUI_DistrTableFrame::Table implementation
00235 // ---
00236 
00237 StdMeshersGUI_DistrTableFrame::Table::
00238 Table( QWidget* parent, int rows )
00239   : QTableWidget( parent ), myFuncMin( 0.0 )
00240 {
00241   setItemDelegate( new StdMeshersGUI_DistrTableFrame::SpinBoxDelegate( this ) );
00242 
00243   setColumnCount( 2 );
00244 
00245   QStringList labs;
00246   labs << "t" << "f(t)";
00247   setHorizontalHeaderLabels( labs );
00248   this->horizontalHeader()->setStretchLastSection(true);
00249   this->horizontalHeader()->setDefaultSectionSize(60);
00250 
00251   while( rows-- )
00252     addRow();
00253 
00254   setUpRows( true );
00255 }
00256 
00257 void
00258 StdMeshersGUI_DistrTableFrame::Table::
00259 setEditor( int r, int c, SMESHGUI_SpinBox* sb )
00260 {
00261   myEditorData.r  = r;
00262   myEditorData.c  = c;
00263   myEditorData.sb = sb;
00264 }
00265 
00266 StdMeshersGUI_DistrTableFrame::Table::
00267 ~Table()
00268 {
00269 }
00270 
00271 QList<double>
00272 StdMeshersGUI_DistrTableFrame::Table::
00273 data()
00274 {
00275   closePersistentEditor( currentItem() );
00276 
00277   QList<double> d;
00278   for ( int r = 0; r < rowCount(); r++ ) {
00279     d.append( value( r, ArgColumn ) );
00280     d.append( value( r, FuncColumn ) );
00281   }
00282   return d;
00283 }
00284 
00285 void
00286 StdMeshersGUI_DistrTableFrame::Table::
00287 setData( const QList<double>& d )
00288 {
00289   closePersistentEditor( currentItem() );
00290 
00291   setRowCount( d.count() / 2 );
00292   for ( int r = 0; r < rowCount(); r++ ) {
00293     setValue( r, ArgColumn,  d[r*2]   );
00294     setValue( r, FuncColumn, d[r*2+1] );
00295   }
00296 }
00297 
00298 double
00299 StdMeshersGUI_DistrTableFrame::Table::
00300 value( int r, int c ) const
00301 {
00302   if ( r < 0 || r > rowCount() || c < 0 || c > columnCount() || !item( r, c ) )
00303     return 0.0;
00304 
00305   return item( r, c )->text().toDouble();
00306 }
00307 
00308 void
00309 StdMeshersGUI_DistrTableFrame::Table::
00310 setValue( int r, int c, double v )
00311 {
00312   if ( r < 0 || r > rowCount() || c < 0 || c > columnCount() )
00313     return;
00314 
00315   if ( c == FuncColumn && v < funcMinimum( r ) )
00316     v = funcMinimum( r ); // correct func value according to the valid min value
00317   if ( c == FuncColumn && v > funcMaximum( r ) )
00318     v = funcMaximum( r ); // correct func value according to the valid max value
00319   else if ( r == ArgColumn && v < argMinimum( r ) )
00320     v = argMinimum( r );  // correct arg  value according to the valid min value
00321   else if ( r == ArgColumn && v > argMaximum( r ) )
00322     v = argMaximum( r );  // correct arg  value according to the valid max value
00323 
00324   if ( !item( r, c ) )
00325     setItem( r, c, new QTableWidgetItem );
00326   item( r, c )->setText( QString::number( v ) );
00327 }
00328 
00329 double
00330 StdMeshersGUI_DistrTableFrame::Table::
00331 argMinimum( int r ) const
00332 {
00333   // for the first row the minimum value is always 0.0
00334   // for the other rows the minumum value is the above row's value
00335   double val = 0.0;
00336   if ( r > 0 && r < rowCount() )
00337     val = value( r-1, ArgColumn );
00338   return val;
00339 }
00340 
00341 double
00342 StdMeshersGUI_DistrTableFrame::Table::
00343 argMaximum( int r ) const
00344 {
00345   // for the last row the maximum value is always 1.0
00346   // for the other rows the maxumum value is the below row's value
00347   double val = 1.0;
00348   if ( r >= 0 && r < rowCount()-1 ) {
00349     val = value( r+1, ArgColumn );
00350   }
00351   return val;
00352 }
00353 
00354 double
00355 StdMeshersGUI_DistrTableFrame::Table::
00356 argStep( int /*r*/ ) const
00357 {
00358   // correct this to provide more smart behaviour if needed
00359   return 0.1;
00360 }
00361 
00362 double
00363 StdMeshersGUI_DistrTableFrame::Table::
00364 funcMinimum( int /*r*/ ) const
00365 {
00366   // correct this to provide more smart behaviour if needed
00367   return myFuncMin;
00368 }
00369 
00370 double
00371 StdMeshersGUI_DistrTableFrame::Table::
00372 funcMaximum( int /*r*/ ) const
00373 {
00374   // correct this to provide more smart behaviour if needed
00375   return 1e20;
00376 }
00377 
00378 double
00379 StdMeshersGUI_DistrTableFrame::Table::
00380 funcStep( int /*r*/ ) const
00381 {
00382   // correct this to provide more smart behaviour if needed
00383   return 1.0;
00384 }
00385 
00386 void
00387 StdMeshersGUI_DistrTableFrame::Table::
00388 setFuncMinValue( double val )
00389 {
00390   myFuncMin = val;
00391 
00392   QTableWidgetItem* i = currentItem();
00393   if ( i && 
00394        i->row()    == myEditorData.r && 
00395        i->column() == myEditorData.c && 
00396        i->column() == FuncColumn     &&
00397        myEditorData.sb ) {
00398     myEditorData.sb->setMinimum( myFuncMin );
00399   }
00400   else {
00401     closePersistentEditor( currentItem() );
00402   }
00403 
00404   for ( int r = 0; r < rowCount(); r++ ) {
00405     double v = item( r, FuncColumn )->text().toDouble();
00406     if ( v < myFuncMin ) 
00407       item( r, FuncColumn )->setText( QString::number( myFuncMin ) );
00408   }
00409 }
00410 
00411 QSize
00412 StdMeshersGUI_DistrTableFrame::Table::
00413 sizeHint() const
00414 {
00415   if( cachedSizeHint().isValid() )
00416     return cachedSizeHint();
00417   return QTableWidget::sizeHint();
00418 //   QSize sh = QTableWidget::sizeHint();
00419 //   if( sh.width() < 400 )
00420 //     sh.setWidth( 400 );
00421 //   if( sh.height() < 200 )
00422 //     sh.setHeight( 200 );
00423 // 
00424 //   setCachedSizeHint( sh );
00425 //   return sh;
00426 }
00427 
00428 void
00429 StdMeshersGUI_DistrTableFrame::Table::
00430 addRow()
00431 {
00432   int r = currentRow() >= 0 ? currentRow() : ( rowCount() > 0 ? rowCount() - 1 : 0 );
00433   insertRow( r );
00434 
00435   double argMin  = argMinimum( r );
00436   double funcMin = funcMinimum( r );
00437   
00438   setItem( r, ArgColumn,  new QTableWidgetItem( QString::number( argMin ) ) );
00439   setItem( r, FuncColumn, new QTableWidgetItem( QString::number( funcMin ) ) );
00440 }
00441 
00442 void
00443 StdMeshersGUI_DistrTableFrame::Table::
00444 deleteRow()
00445 {
00446   QList<int> selRows = selectedRows();
00447   for ( int r = selRows.count()-1; r >= 0; r-- )
00448     removeRow( r );
00449 }
00450 
00451 void
00452 StdMeshersGUI_DistrTableFrame::Table::
00453 closeEditor( QWidget* editor, QAbstractItemDelegate::EndEditHint hint )
00454 {
00455   myEditorData.reset();
00456   QTableWidget::closeEditor( editor, hint );
00457 }
00458 
00459 void
00460 StdMeshersGUI_DistrTableFrame::Table::
00461 setUpRows( bool autoset )
00462 {
00463   if ( rowCount() < 1 )
00464     return;
00465   if ( autoset ) {
00466     double s = argMaximum( rowCount()-1 ) / rowCount();
00467     for ( int r = 0; r < rowCount()-1; r++ )
00468       setValue( r, ArgColumn, r * s );
00469     setValue( rowCount()-1, ArgColumn, argMaximum( rowCount()-1 ) );
00470   }
00471   else {
00472     // TODO
00473   }
00474 }
00475 
00476 QSize
00477 StdMeshersGUI_DistrTableFrame::Table::
00478 cachedSizeHint() const
00479 {
00480   return myCachedSizeHint;
00481 }
00482 
00483 void
00484 StdMeshersGUI_DistrTableFrame::Table::
00485 setCachedSizeHint( const QSize& s ) const
00486 {
00487   Table* that = const_cast<Table*>( this );
00488   that->myCachedSizeHint = s;
00489 }
00490 
00491 QList<int>
00492 StdMeshersGUI_DistrTableFrame::Table::
00493 selectedRows()
00494 {
00495   QList<int> l;
00496   QList<QTableWidgetItem*> selItems = selectedItems();
00497   QTableWidgetItem* i;
00498   foreach( i, selItems )
00499     if ( !l.contains( i->row() ) ) l.append( i->row() );
00500   qSort( l );
00501   return l;
00502 }
00503 
00509 StdMeshersGUI_DistrTableFrame::
00510 StdMeshersGUI_DistrTableFrame( QWidget* parent )
00511   : QWidget( parent )
00512 {
00513   QGridLayout* main = new QGridLayout( this );
00514   main->setMargin( 0 );
00515   main->setSpacing( 0 );
00516 
00517   // ---
00518   myTable = new Table( this );
00519   connect( myTable, SIGNAL( valueChanged( int, int ) ), this, SIGNAL( valueChanged( int, int ) ) );
00520 
00521   myButtons[ InsertRowBtn ] = new QPushButton( tr( "SMESH_INSERT_ROW" ), this );
00522   myButtons[ RemoveRowBtn ] = new QPushButton( tr( "SMESH_REMOVE_ROW" ), this );
00523 
00524 
00525   // ---
00526   main->addWidget( myTable , 0, 0, 1, 3);
00527   main->addWidget( myButtons[ InsertRowBtn ] , 1, 0);
00528   main->addWidget( myButtons[ RemoveRowBtn ] , 1, 1);
00529   main->setColumnStretch(2, 1);
00530   main->setSpacing( SPACING );
00531   
00532   // ---
00533   connect( myButtons[ InsertRowBtn ], SIGNAL( clicked() ), this, SLOT( onInsert() ) );
00534   connect( myButtons[ RemoveRowBtn ], SIGNAL( clicked() ), this, SLOT( onRemove() ) );
00535   connect( myTable, SIGNAL( currentCellChanged( int, int, int, int ) ),
00536            this,    SIGNAL( currentChanged( int, int ) ) );
00537   connect( myTable, SIGNAL( cellChanged( int, int ) ),
00538            this,    SIGNAL( valueChanged( int, int ) ) );
00539 }
00540 
00541 StdMeshersGUI_DistrTableFrame::
00542 ~StdMeshersGUI_DistrTableFrame()
00543 {
00544 }
00545 
00546 void
00547 StdMeshersGUI_DistrTableFrame::
00548 showButton( const TableButton b, const bool on )
00549 {
00550   if ( button( b ) ) button( b )->setVisible( on );
00551 }
00552 
00553 bool
00554 StdMeshersGUI_DistrTableFrame::
00555 isButtonShown( const TableButton b ) const
00556 {
00557   return button( b ) ? button( b )->isVisible() : false;
00558 }
00559   
00560 void
00561 StdMeshersGUI_DistrTableFrame::
00562 data( DataArray& array ) const
00563 {
00564   QList<double> d = myTable->data();
00565   sortData( d );
00566 
00567   array.length( d.count() );
00568   for ( int i = 0; i < d.count(); i++ )
00569     array[i] = d[i];
00570 }
00571 
00572 void
00573 StdMeshersGUI_DistrTableFrame::
00574 setData( const DataArray& array )
00575 {
00576   QList<double> d;
00577   for ( int i = 0; i < array.length(); i++ )
00578     d.append( array[i] );
00579 
00580   sortData( d );
00581   myTable->setData( d );
00582 }
00583 
00584 void
00585 StdMeshersGUI_DistrTableFrame::
00586 setFuncMinValue( double v )
00587 {
00588   myTable->setFuncMinValue( v );
00589 }
00590 
00591 QPushButton*
00592 StdMeshersGUI_DistrTableFrame::
00593 button( const TableButton b ) const
00594 {
00595   return myButtons.contains( b ) ? myButtons[ b ] : 0;
00596 }
00597 
00598 void
00599 StdMeshersGUI_DistrTableFrame::
00600 onInsert()
00601 {
00602   myTable->addRow();
00603 }
00604 
00605 void
00606 StdMeshersGUI_DistrTableFrame::
00607 onRemove()
00608 {
00609   myTable->deleteRow();
00610 }