Salome HOME
a68b6c9c71ad5b4239604b66a3946b4708b9e50d
[modules/smesh.git] / src / StdMeshersGUI / StdMeshersGUI_DistrTable.cxx
1 //  SMESH StdMeshersGUI
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
21 //
22 //
23 //
24 //  File   : StdMeshersGUI_DistrTable.cxx
25 //  Module : SMESH
26 //  $Header$
27
28 #include "StdMeshersGUI_DistrTable.h"
29 #include <QtxDblValidator.h>
30
31 #include <qlayout.h>
32 #include <qpushbutton.h>
33 #include <qlineedit.h>
34
35 //=================================================================================
36 // class    : StdMeshersGUI_DistrTable
37 // purpose  :
38 //=================================================================================
39 StdMeshersGUI_DistrTable::StdMeshersGUI_DistrTable( const int rows, QWidget* parent, const char* name )
40 : QTable( rows, 2, parent, name )
41 {
42   horizontalHeader()->setLabel( 0, "t" );
43   horizontalHeader()->setLabel( 1, "f(t)" );
44   myArgV = new QtxDblValidator( 0.0, 1.0, 3, this );
45   myFuncV = new QtxDblValidator( 0.0, 1E20, 3, this );
46 }
47
48 StdMeshersGUI_DistrTable::~StdMeshersGUI_DistrTable()
49 {
50 }
51
52 QSize StdMeshersGUI_DistrTable::sizeHint() const
53 {
54   if( cachedSizeHint().isValid() )
55     return cachedSizeHint();
56
57   constPolish();
58
59   QSize sh = QScrollView::sizeHint();
60   if( sh.width()<400 )
61     sh.setWidth( 400 );
62   if( sh.height()<200 )
63     sh.setHeight( 200 );
64
65   setCachedSizeHint( sh );
66   return sh;
67 }
68
69 void StdMeshersGUI_DistrTable::stopEditing( const bool accept )
70 {
71   endEdit( currEditRow(), currEditCol(), accept, false );
72 }
73
74 void StdMeshersGUI_DistrTable::edit( const int r, const int c )
75 {
76   if( isEditing() )
77     endEdit( currEditRow(), currEditCol(), true, false );
78   clearSelection();
79   setCurrentCell( r, c );
80   if( beginEdit( r, c, false ) )
81     setEditMode( Editing, r, c );
82   QTableSelection sel;
83   sel.init( r, c );
84   sel.expandTo( r, c );
85   addSelection( sel );
86 }
87
88 bool StdMeshersGUI_DistrTable::eventFilter( QObject* o, QEvent* e )
89 {
90   if( e && e->type()==QEvent::KeyPress )
91   {
92     QKeyEvent* ke = ( QKeyEvent* )e;
93     int k = ke->key();
94     if( k==Qt::Key_Tab || k==Qt::Key_BackTab || k==Qt::Key_Return || k==Qt::Key_Up || k==Qt::Key_Down )
95     {
96       keyPressEvent( ke );
97       return true;
98     }
99   }
100   return QTable::eventFilter( o, e );
101 }
102
103 void StdMeshersGUI_DistrTable::keyPressEvent( QKeyEvent* e )
104 {
105   if( e )
106   {
107     int r = currentRow(), c = currentColumn(), nr, nc;
108     bool shift = e->state() & Qt::ShiftButton, cr = false;
109     switch( e->key() )
110     {
111     case Qt::Key_Tab:
112       nc = c+1;
113       nr = r;
114       break;
115
116     case Qt::Key_BackTab:
117       nc = c-1;
118       nr = r;
119       break;
120
121     case Qt::Key_Return:
122       nc = 0;
123       nr = shift ? r-1 : r+1;
124       cr = true;
125       break;
126
127     case Qt::Key_Up:
128       nc = c;
129       nr = r-1;
130       break;
131
132     case Qt::Key_Down:
133       nc = c;
134       nr = r+1;
135       break;
136
137     default:
138       QTable::keyPressEvent( e );
139       return;
140     }
141
142     if( nc<0 )
143     {
144       nc=1; nr--;
145     }
146     if( nc>1 )
147     {
148       nc=0; nr++;
149     }
150
151     if( nr>=numRows() && cr )
152     {
153       if( isEditing() )
154         endEdit( currEditRow(), currEditCol(), true, false );
155       onEdit( INSERT_ROW, nr );
156     }
157
158     else if( nr<0 || nr>=numRows() )
159     {
160       nr = r; nc = c;   
161     }
162     edit( nr, nc );
163     e->accept();
164   }
165 }
166
167 QWidget* StdMeshersGUI_DistrTable::createEditor( int r, int c, bool init ) const
168 {
169   QWidget* w = QTable::createEditor( r, c, init );
170   if( w )
171   {
172     //w->installEventFilter( this );
173     if( w->inherits( "QLineEdit" ) )
174     {
175       QLineEdit* le = ( QLineEdit* )w;
176       le->setValidator( c==0 ? myArgV : myFuncV );
177     }
178   }
179   
180   return w;
181 }
182
183 void StdMeshersGUI_DistrTable::onEdit( TableButton b, int cur )
184 {
185   switch( b )
186   {     
187   case INSERT_ROW:
188     setNumRows( numRows()+1 );
189     for( int i=numRows()-1; i>=cur; i-- )
190       for( int j=0; j<numCols(); j++ )
191         if( i>cur )
192           setText( i, j, text( i-1, j ) );
193         else
194           setText( i, j, "0" );
195     emit( valueChanged( cur, 0 ) );
196     break;
197       
198   case REMOVE_ROW:
199     if( numRows()>1 )
200     {
201       for( int i=cur; i<numRows(); i++ )
202         for( int j=0; j<numCols(); j++ )
203           setText( i, j, text( i+1, j ) );
204       setNumRows( numRows()-1 );
205     }
206     emit( valueChanged( cur, 0 ) );
207     break;
208   }
209 }
210
211 void StdMeshersGUI_DistrTable::sortData( SMESH::double_array& arr )
212 {
213   QValueList< QPair<double,double> > aData;
214   if( arr.length()%2==1 )
215     arr.length( arr.length()-1 );
216
217   int aLen = arr.length();
218   for( int i=0; i<aLen/2; i++ )
219     aData.append( QPair<double,double>( arr[2*i], arr[2*i+1] ) );
220
221   qHeapSort( aData );
222
223   QValueList< QPair<double,double> >::const_iterator anIt = aData.begin(), aLast = aData.end();
224   QValueList<double> unique_values;
225   double prev; int i=0;
226   if( (*anIt).first>0.0 )
227   {
228     unique_values.append( 0.0 );
229     unique_values.append( (*anIt).second );
230     i++; prev = 0.0;
231   }
232   for( ; anIt!=aLast; anIt++ )
233   {
234     if( i==0 || (*anIt).first>prev )
235     {
236       unique_values.append( (*anIt).first );
237       unique_values.append( (*anIt).second );
238       i++;
239     }
240     prev = (*anIt).first;
241   }
242   if( prev<1.0 )
243   {
244     unique_values.append( 1.0 );
245     anIt--;
246     unique_values.append( (*anIt).second );
247   }
248
249   arr.length( unique_values.count() );
250   QValueList<double>::const_iterator anIt1 = unique_values.begin(), aLast1 = unique_values.end();
251   for( int j=0; anIt1!=aLast1; anIt1++, j++ )
252     arr[j] = *anIt1;
253 }
254
255 void StdMeshersGUI_DistrTable::data( SMESH::double_array& v )
256 {
257   stopEditing( true );
258   v.length( 2*numRows() );
259   for( int i=0; i<numRows(); i++ )
260     for( int j=0; j<numCols(); j++ )
261       v[numCols()*i+j] = text( i, j ).toDouble();
262   sortData( v );
263 }
264
265 void StdMeshersGUI_DistrTable::setData( const SMESH::double_array& d )
266 {
267   stopEditing( false );
268   setNumRows( d.length()/2 );
269   QString val;
270   for( int i=0; i<d.length(); i++ )
271   {
272     QtxDblValidator* v = i%2==0 ? myArgV : myFuncV;
273     val = QString::number( d[i] );
274     v->fixup( val );
275     setText( i/2, i%2, val );
276   }
277 }
278
279 QtxDblValidator* StdMeshersGUI_DistrTable::argValidator() const
280 {
281   return myArgV;
282 }
283
284 QtxDblValidator* StdMeshersGUI_DistrTable::funcValidator() const
285 {
286   return myFuncV;
287 }
288
289 //=================================================================================
290 // class    : StdMeshersGUI_DistrTableFrame
291 // purpose  :
292 //=================================================================================
293 StdMeshersGUI_DistrTableFrame::StdMeshersGUI_DistrTableFrame( QWidget* parent )
294 : QFrame( parent )
295 {
296   QVBoxLayout* main = new QVBoxLayout( this, 0, 0 );
297
298   myTable = new StdMeshersGUI_DistrTable( 1, this );
299   connect( myTable, SIGNAL( valueChanged( int, int ) ), this, SIGNAL( valueChanged( int, int ) ) );
300   connect( this, SIGNAL( toEdit( TableButton, int ) ), myTable, SLOT( onEdit( TableButton, int ) ) );
301   
302   QFrame* aButFrame = new QFrame( this );
303   QHBoxLayout* butLay = new QHBoxLayout( aButFrame, 5, 5 );
304
305   myInsertRow = new QPushButton( tr( "SMESH_INSERT_ROW" ), aButFrame );
306   myRemoveRow = new QPushButton( tr( "SMESH_REMOVE_ROW" ), aButFrame );
307
308   butLay->addWidget( myInsertRow, 0 );
309   butLay->addWidget( myRemoveRow, 0 );
310   butLay->addStretch( 1 );
311
312   main->addWidget( myTable, 1 );
313   main->addWidget( aButFrame, 0 );
314
315   connect( myInsertRow, SIGNAL( clicked() ), this, SLOT( onButtonClicked() ) );
316   connect( myRemoveRow, SIGNAL( clicked() ), this, SLOT( onButtonClicked() ) );
317 }
318
319 StdMeshersGUI_DistrTableFrame::~StdMeshersGUI_DistrTableFrame()
320 {
321 }
322
323 StdMeshersGUI_DistrTable* StdMeshersGUI_DistrTableFrame::table() const
324 {
325   return myTable;
326 }
327
328 void StdMeshersGUI_DistrTableFrame::setShown( const TableButton b, const bool sh )
329 {
330   if( button( b ) )
331     button( b )->setShown( sh );
332 }
333
334 bool StdMeshersGUI_DistrTableFrame::isShown( const TableButton b ) const
335 {
336   bool res = false;
337   if( button( b ) )
338     res = button( b )->isShown();
339   return res;
340 }
341
342 QButton* StdMeshersGUI_DistrTableFrame::button( const TableButton b ) const
343 {
344   QButton* res = 0;
345   switch( b )
346   {
347     case INSERT_ROW:
348       res = myInsertRow;
349       break;
350
351     case REMOVE_ROW:
352       res = myRemoveRow;
353       break;
354   }
355   return res;
356 }
357
358 void StdMeshersGUI_DistrTableFrame::onButtonClicked()
359 {
360   if( sender()==button( INSERT_ROW ) )
361     emit toEdit( INSERT_ROW, table()->currentRow() );
362     
363   else if( sender()==button( REMOVE_ROW ) )
364     emit toEdit( REMOVE_ROW, table()->currentRow() );
365 }
366