]> SALOME platform Git repositories - modules/gui.git/blob - src/Qtx/QtxDblSpinBox.cxx
Salome HOME
Initial version
[modules/gui.git] / src / Qtx / QtxDblSpinBox.cxx
1 // File:      QtxDblSpinBox.cxx
2 // Author:    Sergey TELKOV
3
4 #include "QtxDblSpinBox.h"
5
6 #include <qlineedit.h>
7 #include <qvalidator.h>
8 #include <qapplication.h>
9
10 /*
11         Class: QtxDblSpinBox::Validator [internal]
12         Descr: Validator for QtxDblSpinBox (getted from Trolltech Qt - SpinBoxValidator)
13 */
14
15 class QtxDblSpinBox::Validator : public QDoubleValidator
16 {
17 public:
18     Validator( QtxDblSpinBox* sb, const char* name )
19         : QDoubleValidator( sb, name ), spinBox( sb ) {}
20
21     virtual State validate( QString& str, int& pos ) const;
22
23 private:
24     QtxDblSpinBox* spinBox;
25 };
26
27 QValidator::State QtxDblSpinBox::Validator::validate( QString& str, int& pos ) const
28 {
29   QString pref = spinBox->prefix();
30   QString suff = spinBox->suffix();
31   uint overhead = pref.length() + suff.length();
32   State state = Invalid;
33
34   if ( overhead == 0 )
35           state = QDoubleValidator::validate( str, pos );
36   else
37         {
38                 if ( str.length() >= overhead && str.startsWith( pref ) &&
39          str.right( suff.length() ) == suff )
40                 {
41                         QString core = str.mid( pref.length(), str.length() - overhead );
42                         int corePos = pos - pref.length();
43                         state = QDoubleValidator::validate( core, corePos );
44                         pos = corePos + pref.length();
45                         str.replace( pref.length(), str.length() - overhead, core );
46                 }
47                 else
48                 {
49                         state = QDoubleValidator::validate( str, pos );
50                         if ( state == Invalid )
51                         {
52                                 QString special = spinBox->specialValueText().stripWhiteSpace();
53                                 QString candidate = str.stripWhiteSpace();
54                                 if ( special.startsWith( candidate ) )
55                                 {
56                                         if ( candidate.length() == special.length() )
57                                                 state = Acceptable;
58                                         else
59                                                 state = Intermediate;
60                                 }
61                         }
62                 }
63   }
64   return state;
65 }
66
67 /*
68         Class: QtxDblSpinBox
69         Descr: Spin box for real numbers.
70 */
71
72 QtxDblSpinBox::QtxDblSpinBox( QWidget* parent, const char* name )
73 : QSpinBox( parent, name ),
74 myCleared( false ),
75 myBlocked( false ),
76 myPrecision( 0 )
77 {
78   myMin = QRangeControl::minValue();
79   myMax = QRangeControl::maxValue();
80   myStep = QRangeControl::lineStep();
81         myValue = myMin;
82   setValidator( new Validator( this, "double_spinbox_validator" ) );
83   rangeChange();
84   updateDisplay();
85 }
86
87 QtxDblSpinBox::QtxDblSpinBox( double min, double max, double step, QWidget* parent, const char* name )
88 : QSpinBox( parent, name ),
89 myMin( min ),
90 myMax( max ),
91 myStep( step ),
92 myCleared( false ),
93 myBlocked( false ),
94 myPrecision( 0 )
95 {
96         myValue = myMin;
97   setValidator( new Validator( this, "double_spinbox_validator" ) );
98   rangeChange();
99   updateDisplay();
100 }
101
102 QtxDblSpinBox::~QtxDblSpinBox()
103 {
104 }
105
106 double QtxDblSpinBox::minValue() const
107 {
108   return myMin;
109 }
110
111 double QtxDblSpinBox::maxValue() const
112 {
113   return myMax;
114 }
115
116 void QtxDblSpinBox::setMinValue( int min )
117 {
118         setMinValue( (double)min );
119 }
120
121 void QtxDblSpinBox::setMinValue( double min )
122 {
123   if ( myMin != min )
124   {
125     myMin = min;
126     rangeChange();
127   }
128 }
129
130 void QtxDblSpinBox::setMaxValue( int max )
131 {
132         setMaxValue( (double)max );
133 }
134
135 void QtxDblSpinBox::setMaxValue( double max )
136 {
137   if ( myMax != max )
138   {
139     myMax = max;
140     rangeChange();
141   }
142 }
143
144 void QtxDblSpinBox::setRange( int min, int max )
145 {
146         setRange( (double)min, (double)max );
147 }
148
149 void QtxDblSpinBox::setRange( double min, double max )
150 {
151   if ( myMin != min || myMax != max )
152   {
153     myMin = min;
154     myMax = max;
155     rangeChange();
156   }
157 }
158
159 double QtxDblSpinBox::lineStep() const
160 {
161   return myStep;
162 }
163
164 void QtxDblSpinBox::setLineStep( int step )
165 {
166   setLineStep( (double)step );
167 }
168
169 void QtxDblSpinBox::setLineStep( double step )
170 {
171   myStep = step;
172 }
173
174 double QtxDblSpinBox::value() const
175 {
176   return myValue;
177 }
178
179 void QtxDblSpinBox::setValue( int val )
180 {
181         setValue( (double)val );
182 }
183
184 void QtxDblSpinBox::setValue( double val )
185 {
186         myCleared = false;
187   double prevVal = myValue;
188   myValue = bound( val );
189   if ( prevVal != myValue )
190     valueChange();
191 }
192
193 void QtxDblSpinBox::stepUp()
194 {
195         interpretText();
196         if ( wrapping() && myValue + myStep > myMax )
197                 setValue( myMin );
198         else
199                 setValue( myValue + myStep );
200 }
201
202 void QtxDblSpinBox::stepDown()
203 {
204         interpretText();
205         if ( wrapping() && myValue - myStep < myMin )
206                 setValue( myMax );
207         else
208                 setValue( myValue - myStep );
209 }
210
211 int QtxDblSpinBox::precision() const
212 {
213         return myPrecision;
214 }
215
216 void QtxDblSpinBox::setPrecision( const int prec )
217 {
218         int newPrec = QMAX( prec, 0 );
219         int oldPrec = QMAX( myPrecision, 0 );
220         myPrecision = prec;
221         if ( newPrec != oldPrec )
222                 updateDisplay();
223 }
224
225 bool QtxDblSpinBox::isCleared() const
226 {
227         return myCleared;
228 }
229
230 void QtxDblSpinBox::setCleared( const bool on )
231 {
232         if ( myCleared == on )
233                 return;
234
235         myCleared = on;
236         updateDisplay();
237 }
238
239 void QtxDblSpinBox::selectAll()
240 {
241 #if QT_VER >= 3
242         QSpinBox::selectAll();
243 #else
244   editor()->selectAll();
245 #endif
246 }
247
248 bool QtxDblSpinBox::eventFilter( QObject* o, QEvent* e )
249 {
250   if ( !myCleared || o != editor() || !editor()->text().stripWhiteSpace().isEmpty() )
251     return QSpinBox::eventFilter( o, e );
252
253   if ( e->type() == QEvent::FocusOut || e->type() == QEvent::Leave || e->type() == QEvent::Hide )
254     return false;
255
256   if ( e->type() == QEvent::KeyPress &&
257           ( ((QKeyEvent*)e)->key() == Key_Tab || ((QKeyEvent*)e)->key() == Key_BackTab ) )
258   {
259     QApplication::sendEvent( this, e );
260     return true;
261   }
262
263   return QSpinBox::eventFilter( o, e );
264 }
265
266 void QtxDblSpinBox::updateDisplay()
267 {
268   if ( myBlocked )
269     return;
270     
271   bool isBlock = myBlocked;
272   myBlocked = true;
273     
274   QString txt = currentValueText();
275     
276   if ( myValue >= myMax )
277     QSpinBox::setValue( QSpinBox::maxValue() );
278   else if ( myValue <= myMin )
279     QSpinBox::setValue( QSpinBox::minValue() );
280   else
281     QSpinBox::setValue( ( QSpinBox::minValue() + QSpinBox::maxValue() ) / 2 );
282     
283   QSpinBox::updateDisplay();
284     
285   editor()->setText( myCleared ? QString::null : txt );
286     
287   myBlocked = isBlock;
288 }
289
290 void QtxDblSpinBox::interpretText()
291 {
292   myCleared = false;
293
294   bool ok = true;
295   bool done = false;
296   double newVal = 0;
297   if ( !specialValueText().isEmpty() )
298   {
299           QString s = QString( text() ).stripWhiteSpace();
300           QString t = QString( specialValueText() ).stripWhiteSpace();
301           if ( s == t )
302     {
303       newVal = minValue();
304             done = true;
305     }
306   }
307   if ( !done )
308           newVal = mapTextToDoubleValue( &ok );
309   if ( ok )
310           setValue( newVal );
311   updateDisplay();
312 }
313
314 void QtxDblSpinBox::valueChange()
315 {
316   updateDisplay();
317   emit valueChanged( value() );
318   emit valueChanged( currentValueText() );
319 }
320
321 void QtxDblSpinBox::rangeChange()
322 {
323   double min = QMIN( myMin, myMax );
324   double max = QMAX( myMin, myMax );
325   myMin = min;
326   myMax = max;
327   if ( validator()->inherits( "QDoubleValidator" ) )
328     ((QDoubleValidator*)validator())->setRange( myMin, myMax );
329
330         if ( myMin == myMax )
331                 QSpinBox::setRange( 0, 0 );
332         else
333                 QSpinBox::setRange( 0, 2 );
334
335   setValue( myValue );
336   updateDisplay();
337 }
338
339 QString QtxDblSpinBox::currentValueText()
340 {
341   QString s;
342   if ( (myValue == minValue()) && !specialValueText().isEmpty() )
343           s = specialValueText();
344   else
345         {
346           s = prefix();
347                 s.append( mapValueToText( myValue ) );
348                 s.append( suffix() );
349         }
350   return s;
351 }
352
353 QString QtxDblSpinBox::mapValueToText( double v )
354 {
355         QString s;
356   s.setNum( v, myPrecision < 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) );
357   return s;
358 }
359
360 QString QtxDblSpinBox::mapValueToText( int )
361 {
362   QString s;
363   s.setNum( myValue, myPrecision < 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) );
364   return s;
365 }
366
367 double QtxDblSpinBox::mapTextToDoubleValue( bool* ok )
368 {
369   QString s = text();
370   double newVal = s.toDouble( ok );
371   if ( !(*ok) && !( !prefix() && !suffix() ) )
372   {
373           s = cleanText();
374           newVal = s.toDouble( ok );
375   }
376   return newVal;
377 }
378
379 double QtxDblSpinBox::bound( double val )
380 {
381   double newVal = val;
382   if ( newVal > myMax )
383     newVal = myMax;
384   if ( newVal < myMin )
385     newVal = myMin;
386   return newVal;
387 }
388
389 void QtxDblSpinBox::leaveEvent( QEvent* e )
390 {
391         if ( !myCleared )
392                 QSpinBox::leaveEvent( e );
393 }
394
395 void QtxDblSpinBox::wheelEvent( QWheelEvent* e )
396 {
397   if ( !isEnabled() )
398     return;
399
400   QSpinBox::wheelEvent( e );
401   updateDisplay();
402 }