1 // Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/
19 // File: QtxDblSpinBox.cxx
20 // Author: Sergey TELKOV
22 #include "QtxDblSpinBox.h"
24 #include <qlineedit.h>
25 #include <qvalidator.h>
26 #include <qapplication.h>
31 Class: QtxDblSpinBox::Validator [internal]
32 Descr: Validator for QtxDblSpinBox (getted from Trolltech Qt - SpinBoxValidator)
35 class QtxDblSpinBox::Validator : public QDoubleValidator
38 Validator( QtxDblSpinBox* sb, const char* name )
39 : QDoubleValidator( sb, name ), spinBox( sb ) {}
41 virtual State validate( QString& str, int& pos ) const;
44 QtxDblSpinBox* spinBox;
47 QValidator::State QtxDblSpinBox::Validator::validate( QString& str, int& pos ) const
49 QString pref = spinBox->prefix();
50 QString suff = spinBox->suffix();
51 uint overhead = pref.length() + suff.length();
52 State state = Invalid;
55 state = QDoubleValidator::validate( str, pos );
58 if ( str.length() >= overhead && str.startsWith( pref ) &&
59 str.right( suff.length() ) == suff )
61 QString core = str.mid( pref.length(), str.length() - overhead );
62 int corePos = pos - pref.length();
63 state = QDoubleValidator::validate( core, corePos );
64 pos = corePos + pref.length();
65 str.replace( pref.length(), str.length() - overhead, core );
69 state = QDoubleValidator::validate( str, pos );
70 if ( state == Invalid )
72 QString special = spinBox->specialValueText().stripWhiteSpace();
73 QString candidate = str.stripWhiteSpace();
74 if ( special.startsWith( candidate ) )
76 if ( candidate.length() == special.length() )
89 Descr: Spin box for real numbers.
92 QtxDblSpinBox::QtxDblSpinBox( QWidget* parent, const char* name )
93 : QSpinBox( parent, name ),
100 myStep = QRangeControl::lineStep();
102 setValidator( new Validator( this, "double_spinbox_validator" ) );
106 connect( editor(), SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) );
109 QtxDblSpinBox::QtxDblSpinBox( double min, double max, double step, QWidget* parent, const char* name )
110 : QSpinBox( parent, name ),
119 setValidator( new Validator( this, "double_spinbox_validator" ) );
123 connect( editor(), SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) );
126 QtxDblSpinBox::~QtxDblSpinBox()
130 double QtxDblSpinBox::minValue() const
135 double QtxDblSpinBox::maxValue() const
140 void QtxDblSpinBox::setMinValue( int min )
142 setMinValue( (double)min );
145 void QtxDblSpinBox::setMinValue( double min )
154 void QtxDblSpinBox::setMaxValue( int max )
156 setMaxValue( (double)max );
159 void QtxDblSpinBox::setMaxValue( double max )
168 void QtxDblSpinBox::setRange( int min, int max )
170 setRange( (double)min, (double)max );
173 void QtxDblSpinBox::setRange( double min, double max )
175 if ( myMin != min || myMax != max )
183 double QtxDblSpinBox::lineStep() const
188 void QtxDblSpinBox::setLineStep( int step )
190 setLineStep( (double)step );
193 void QtxDblSpinBox::setLineStep( double step )
198 double QtxDblSpinBox::value() const
205 void QtxDblSpinBox::setValue( int val )
207 setValue( (double)val );
210 void QtxDblSpinBox::setValue( double val )
213 double prevVal = myValue;
214 myValue = bound( val );
215 if ( prevVal != myValue )
219 void QtxDblSpinBox::stepUp()
222 if ( wrapping() && myValue + myStep > myMax )
225 setValue( myValue + myStep );
228 void QtxDblSpinBox::stepDown()
231 if ( wrapping() && myValue - myStep < myMin )
234 setValue( myValue - myStep );
237 int QtxDblSpinBox::precision() const
242 void QtxDblSpinBox::setPrecision( const int prec )
244 int newPrec = QMAX( prec, 0 );
245 int oldPrec = QMAX( myPrecision, 0 );
247 if ( newPrec != oldPrec )
251 bool QtxDblSpinBox::isCleared() const
256 void QtxDblSpinBox::setCleared( const bool on )
258 if ( myCleared == on )
265 void QtxDblSpinBox::selectAll()
268 QSpinBox::selectAll();
270 editor()->selectAll();
274 bool QtxDblSpinBox::eventFilter( QObject* o, QEvent* e )
276 if ( !myCleared || o != editor() || !editor()->text().stripWhiteSpace().isEmpty() )
278 bool state = QSpinBox::eventFilter( o, e );
279 if ( e->type() == QEvent::FocusOut && o == editor() )
284 if ( e->type() == QEvent::FocusOut || e->type() == QEvent::Leave || e->type() == QEvent::Hide )
287 if ( e->type() == QEvent::KeyPress &&
288 ( ((QKeyEvent*)e)->key() == Key_Tab || ((QKeyEvent*)e)->key() == Key_BackTab ) )
290 QApplication::sendEvent( this, e );
294 return QSpinBox::eventFilter( o, e );
297 void QtxDblSpinBox::updateDisplay()
302 bool upd = editor()->isUpdatesEnabled();
303 editor()->setUpdatesEnabled( false );
305 bool isBlock = myBlocked;
308 QString txt = currentValueText();
310 if ( myValue >= myMax )
311 QSpinBox::setValue( QSpinBox::maxValue() );
312 else if ( myValue <= myMin )
313 QSpinBox::setValue( QSpinBox::minValue() );
315 QSpinBox::setValue( ( QSpinBox::minValue() + QSpinBox::maxValue() ) / 2 );
317 QSpinBox::updateDisplay();
319 editor()->setUpdatesEnabled( upd );
321 editor()->setText( myCleared ? QString::null : txt );
322 if ( !myCleared && editor()->hasFocus() )
324 if ( editor()->text() == specialValueText() )
325 editor()->selectAll();
327 editor()->setSelection( prefix().length(), editor()->text().length() - prefix().length() - suffix().length() );
330 editor()->setCursorPosition( 0 );
335 void QtxDblSpinBox::interpretText()
342 if ( !specialValueText().isEmpty() )
344 QString s = QString( text() ).stripWhiteSpace();
345 QString t = QString( specialValueText() ).stripWhiteSpace();
353 newVal = mapTextToDoubleValue( &ok );
359 void QtxDblSpinBox::valueChange()
362 emit valueChanged( myValue );
363 emit valueChanged( currentValueText() );
366 void QtxDblSpinBox::rangeChange()
368 double min = QMIN( myMin, myMax );
369 double max = QMAX( myMin, myMax );
372 QDoubleValidator* v = ::qt_cast<QDoubleValidator*>( validator() );
374 v->setRange( myMin, myMax );
376 if ( myMin == myMax )
377 QSpinBox::setRange( 0, 0 );
379 QSpinBox::setRange( 0, 2 );
385 QString QtxDblSpinBox::currentValueText()
388 if ( (myValue == minValue()) && !specialValueText().isEmpty() )
389 s = specialValueText();
393 s.append( mapValueToText( myValue ) );
394 s.append( suffix() );
399 QString QtxDblSpinBox::mapValueToText( double v )
402 s.setNum( v, myPrecision >= 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) );
403 return removeTrailingZeroes( s );
406 QString QtxDblSpinBox::mapValueToText( int )
409 s.setNum( myValue, myPrecision >= 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) );
410 return removeTrailingZeroes( s );
413 double QtxDblSpinBox::mapTextToDoubleValue( bool* ok )
416 double newVal = s.toDouble( ok );
417 if ( !(*ok) && !( !prefix() && !suffix() ) )
420 newVal = s.toDouble( ok );
425 double QtxDblSpinBox::bound( double val )
428 if ( newVal > myMax )
430 if ( newVal < myMin )
435 void QtxDblSpinBox::leaveEvent( QEvent* e )
438 QSpinBox::leaveEvent( e );
441 void QtxDblSpinBox::wheelEvent( QWheelEvent* e )
446 QSpinBox::wheelEvent( e );
450 void QtxDblSpinBox::onTextChanged( const QString& str )
456 QString QtxDblSpinBox::removeTrailingZeroes( const QString& src ) const
458 QString delim( "." );
460 int idx = src.findRev( delim );
464 QString iPart = src.left( idx );
465 QString fPart = src.mid( idx + 1 );
467 while ( !fPart.isEmpty() && fPart.at( fPart.length() - 1 ) == '0' )
468 fPart.remove( fPart.length() - 1, 1 );
471 if ( !fPart.isEmpty() )
472 res += delim + fPart;