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>
29 Class: QtxDblSpinBox::Validator [internal]
30 Descr: Validator for QtxDblSpinBox (getted from Trolltech Qt - SpinBoxValidator)
33 class QtxDblSpinBox::Validator : public QDoubleValidator
36 Validator( QtxDblSpinBox* sb, const char* name )
37 : QDoubleValidator( sb, name ), spinBox( sb ) {}
39 virtual State validate( QString& str, int& pos ) const;
42 QtxDblSpinBox* spinBox;
45 QValidator::State QtxDblSpinBox::Validator::validate( QString& str, int& pos ) const
47 QString pref = spinBox->prefix();
48 QString suff = spinBox->suffix();
49 uint overhead = pref.length() + suff.length();
50 State state = Invalid;
53 state = QDoubleValidator::validate( str, pos );
56 if ( str.length() >= overhead && str.startsWith( pref ) &&
57 str.right( suff.length() ) == suff )
59 QString core = str.mid( pref.length(), str.length() - overhead );
60 int corePos = pos - pref.length();
61 state = QDoubleValidator::validate( core, corePos );
62 pos = corePos + pref.length();
63 str.replace( pref.length(), str.length() - overhead, core );
67 state = QDoubleValidator::validate( str, pos );
68 if ( state == Invalid )
70 QString special = spinBox->specialValueText().stripWhiteSpace();
71 QString candidate = str.stripWhiteSpace();
72 if ( special.startsWith( candidate ) )
74 if ( candidate.length() == special.length() )
87 Descr: Spin box for real numbers.
90 QtxDblSpinBox::QtxDblSpinBox( QWidget* parent, const char* name )
91 : QSpinBox( parent, name ),
96 myMin = QRangeControl::minValue();
97 myMax = QRangeControl::maxValue();
98 myStep = QRangeControl::lineStep();
100 setValidator( new Validator( this, "double_spinbox_validator" ) );
104 connect( editor(), SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) );
107 QtxDblSpinBox::QtxDblSpinBox( double min, double max, double step, QWidget* parent, const char* name )
108 : QSpinBox( parent, name ),
117 setValidator( new Validator( this, "double_spinbox_validator" ) );
121 connect( editor(), SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) );
124 QtxDblSpinBox::~QtxDblSpinBox()
128 double QtxDblSpinBox::minValue() const
133 double QtxDblSpinBox::maxValue() const
138 void QtxDblSpinBox::setMinValue( int min )
140 setMinValue( (double)min );
143 void QtxDblSpinBox::setMinValue( double min )
152 void QtxDblSpinBox::setMaxValue( int max )
154 setMaxValue( (double)max );
157 void QtxDblSpinBox::setMaxValue( double max )
166 void QtxDblSpinBox::setRange( int min, int max )
168 setRange( (double)min, (double)max );
171 void QtxDblSpinBox::setRange( double min, double max )
173 if ( myMin != min || myMax != max )
181 double QtxDblSpinBox::lineStep() const
186 void QtxDblSpinBox::setLineStep( int step )
188 setLineStep( (double)step );
191 void QtxDblSpinBox::setLineStep( double step )
196 double QtxDblSpinBox::value() const
203 void QtxDblSpinBox::setValue( int val )
205 setValue( (double)val );
208 void QtxDblSpinBox::setValue( double val )
211 double prevVal = myValue;
212 myValue = bound( val );
213 if ( prevVal != myValue )
217 void QtxDblSpinBox::stepUp()
220 if ( wrapping() && myValue + myStep > myMax )
223 setValue( myValue + myStep );
226 void QtxDblSpinBox::stepDown()
229 if ( wrapping() && myValue - myStep < myMin )
232 setValue( myValue - myStep );
235 int QtxDblSpinBox::precision() const
240 void QtxDblSpinBox::setPrecision( const int prec )
242 int newPrec = QMAX( prec, 0 );
243 int oldPrec = QMAX( myPrecision, 0 );
245 if ( newPrec != oldPrec )
249 bool QtxDblSpinBox::isCleared() const
254 void QtxDblSpinBox::setCleared( const bool on )
256 if ( myCleared == on )
263 void QtxDblSpinBox::selectAll()
266 QSpinBox::selectAll();
268 editor()->selectAll();
272 bool QtxDblSpinBox::eventFilter( QObject* o, QEvent* e )
274 if ( e->type() == QEvent::FocusOut && o == editor() )
277 if ( !myCleared || o != editor() || !editor()->text().stripWhiteSpace().isEmpty() )
278 return QSpinBox::eventFilter( o, e );
280 if ( e->type() == QEvent::FocusOut || e->type() == QEvent::Leave || e->type() == QEvent::Hide )
283 if ( e->type() == QEvent::KeyPress &&
284 ( ((QKeyEvent*)e)->key() == Key_Tab || ((QKeyEvent*)e)->key() == Key_BackTab ) )
286 QApplication::sendEvent( this, e );
290 return QSpinBox::eventFilter( o, e );
293 void QtxDblSpinBox::updateDisplay()
298 bool upd = editor()->isUpdatesEnabled();
299 editor()->setUpdatesEnabled( false );
301 bool isBlock = myBlocked;
304 QString txt = currentValueText();
306 if ( myValue >= myMax )
307 QSpinBox::setValue( QSpinBox::maxValue() );
308 else if ( myValue <= myMin )
309 QSpinBox::setValue( QSpinBox::minValue() );
311 QSpinBox::setValue( ( QSpinBox::minValue() + QSpinBox::maxValue() ) / 2 );
313 QSpinBox::updateDisplay();
315 editor()->setUpdatesEnabled( upd );
317 editor()->setText( myCleared ? QString::null : txt );
318 if ( !myCleared && editor()->hasFocus() )
320 if ( editor()->text() == specialValueText() )
321 editor()->selectAll();
323 editor()->setSelection( prefix().length(), editor()->text().length() - prefix().length() - suffix().length() );
326 editor()->setCursorPosition( 0 );
331 void QtxDblSpinBox::interpretText()
338 if ( !specialValueText().isEmpty() )
340 QString s = QString( text() ).stripWhiteSpace();
341 QString t = QString( specialValueText() ).stripWhiteSpace();
349 newVal = mapTextToDoubleValue( &ok );
355 void QtxDblSpinBox::valueChange()
358 emit valueChanged( myValue );
359 emit valueChanged( currentValueText() );
362 void QtxDblSpinBox::rangeChange()
364 double min = QMIN( myMin, myMax );
365 double max = QMAX( myMin, myMax );
368 QDoubleValidator* v = ::qt_cast<QDoubleValidator*>( validator() );
370 v->setRange( myMin, myMax );
372 if ( myMin == myMax )
373 QSpinBox::setRange( 0, 0 );
375 QSpinBox::setRange( 0, 2 );
381 QString QtxDblSpinBox::currentValueText()
384 if ( (myValue == minValue()) && !specialValueText().isEmpty() )
385 s = specialValueText();
389 s.append( mapValueToText( myValue ) );
390 s.append( suffix() );
395 QString QtxDblSpinBox::mapValueToText( double v )
398 s.setNum( v, myPrecision >= 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) );
399 return removeTrailingZeroes( s );
402 QString QtxDblSpinBox::mapValueToText( int )
405 s.setNum( myValue, myPrecision >= 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) );
406 return removeTrailingZeroes( s );
409 double QtxDblSpinBox::mapTextToDoubleValue( bool* ok )
412 double newVal = s.toDouble( ok );
413 if ( !(*ok) && !( !prefix() && !suffix() ) )
416 newVal = s.toDouble( ok );
421 double QtxDblSpinBox::bound( double val )
424 if ( newVal > myMax )
426 if ( newVal < myMin )
431 void QtxDblSpinBox::leaveEvent( QEvent* e )
434 QSpinBox::leaveEvent( e );
437 void QtxDblSpinBox::wheelEvent( QWheelEvent* e )
442 QSpinBox::wheelEvent( e );
446 void QtxDblSpinBox::onTextChanged( const QString& str )
452 QString QtxDblSpinBox::removeTrailingZeroes( const QString& src ) const
454 QString delim( "." );
456 int idx = src.findRev( delim );
460 QString iPart = src.left( idx );
461 QString fPart = src.mid( idx + 1 );
463 while ( !fPart.isEmpty() && fPart.at( fPart.length() - 1 ) == '0' )
464 fPart.remove( fPart.length() - 1, 1 );
467 if ( !fPart.isEmpty() )
468 res += delim + fPart;