]> SALOME platform Git repositories - modules/gui.git/blob - src/Qtx/QtxDblSpinBox.cxx
Salome HOME
IPAL9146
[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   connect( editor(), SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) );
87 }
88
89 QtxDblSpinBox::QtxDblSpinBox( double min, double max, double step, QWidget* parent, const char* name )
90 : QSpinBox( parent, name ),
91 myMin( min ),
92 myMax( max ),
93 myStep( step ),
94 myCleared( false ),
95 myBlocked( false ),
96 myPrecision( 0 )
97 {
98         myValue = myMin;
99   setValidator( new Validator( this, "double_spinbox_validator" ) );
100   rangeChange();
101   updateDisplay();
102
103   connect( editor(), SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) );
104 }
105
106 QtxDblSpinBox::~QtxDblSpinBox()
107 {
108 }
109
110 double QtxDblSpinBox::minValue() const
111 {
112   return myMin;
113 }
114
115 double QtxDblSpinBox::maxValue() const
116 {
117   return myMax;
118 }
119
120 void QtxDblSpinBox::setMinValue( int min )
121 {
122         setMinValue( (double)min );
123 }
124
125 void QtxDblSpinBox::setMinValue( double min )
126 {
127   if ( myMin != min )
128   {
129     myMin = min;
130     rangeChange();
131   }
132 }
133
134 void QtxDblSpinBox::setMaxValue( int max )
135 {
136         setMaxValue( (double)max );
137 }
138
139 void QtxDblSpinBox::setMaxValue( double max )
140 {
141   if ( myMax != max )
142   {
143     myMax = max;
144     rangeChange();
145   }
146 }
147
148 void QtxDblSpinBox::setRange( int min, int max )
149 {
150         setRange( (double)min, (double)max );
151 }
152
153 void QtxDblSpinBox::setRange( double min, double max )
154 {
155   if ( myMin != min || myMax != max )
156   {
157     myMin = min;
158     myMax = max;
159     rangeChange();
160   }
161 }
162
163 double QtxDblSpinBox::lineStep() const
164 {
165   return myStep;
166 }
167
168 void QtxDblSpinBox::setLineStep( int step )
169 {
170   setLineStep( (double)step );
171 }
172
173 void QtxDblSpinBox::setLineStep( double step )
174 {
175   myStep = step;
176 }
177
178 double QtxDblSpinBox::value() const
179 {
180   return myValue;
181 }
182
183 void QtxDblSpinBox::setValue( int val )
184 {
185         setValue( (double)val );
186 }
187
188 void QtxDblSpinBox::setValue( double val )
189 {
190         myCleared = false;
191   double prevVal = myValue;
192   myValue = bound( val );
193   if ( prevVal != myValue )
194     valueChange();
195 }
196
197 void QtxDblSpinBox::stepUp()
198 {
199         interpretText();
200         if ( wrapping() && myValue + myStep > myMax )
201                 setValue( myMin );
202         else
203                 setValue( myValue + myStep );
204 }
205
206 void QtxDblSpinBox::stepDown()
207 {
208         interpretText();
209         if ( wrapping() && myValue - myStep < myMin )
210                 setValue( myMax );
211         else
212                 setValue( myValue - myStep );
213 }
214
215 int QtxDblSpinBox::precision() const
216 {
217         return myPrecision;
218 }
219
220 void QtxDblSpinBox::setPrecision( const int prec )
221 {
222         int newPrec = QMAX( prec, 0 );
223         int oldPrec = QMAX( myPrecision, 0 );
224         myPrecision = prec;
225         if ( newPrec != oldPrec )
226                 updateDisplay();
227 }
228
229 bool QtxDblSpinBox::isCleared() const
230 {
231         return myCleared;
232 }
233
234 void QtxDblSpinBox::setCleared( const bool on )
235 {
236         if ( myCleared == on )
237                 return;
238
239         myCleared = on;
240         updateDisplay();
241 }
242
243 void QtxDblSpinBox::selectAll()
244 {
245 #if QT_VER >= 3
246         QSpinBox::selectAll();
247 #else
248   editor()->selectAll();
249 #endif
250 }
251
252 bool QtxDblSpinBox::eventFilter( QObject* o, QEvent* e )
253 {
254   if ( !myCleared || o != editor() || !editor()->text().stripWhiteSpace().isEmpty() )
255     return QSpinBox::eventFilter( o, e );
256
257   if ( e->type() == QEvent::FocusOut || e->type() == QEvent::Leave || e->type() == QEvent::Hide )
258     return false;
259
260   if ( e->type() == QEvent::KeyPress &&
261           ( ((QKeyEvent*)e)->key() == Key_Tab || ((QKeyEvent*)e)->key() == Key_BackTab ) )
262   {
263     QApplication::sendEvent( this, e );
264     return true;
265   }
266
267   return QSpinBox::eventFilter( o, e );
268 }
269
270 void QtxDblSpinBox::updateDisplay()
271 {
272   if ( myBlocked )
273     return;
274     
275   bool isBlock = myBlocked;
276   myBlocked = true;
277     
278   QString txt = currentValueText();
279     
280   if ( myValue >= myMax )
281     QSpinBox::setValue( QSpinBox::maxValue() );
282   else if ( myValue <= myMin )
283     QSpinBox::setValue( QSpinBox::minValue() );
284   else
285     QSpinBox::setValue( ( QSpinBox::minValue() + QSpinBox::maxValue() ) / 2 );
286     
287   QSpinBox::updateDisplay();
288     
289   editor()->setText( myCleared ? QString::null : txt );
290     
291   myBlocked = isBlock;
292 }
293
294 void QtxDblSpinBox::interpretText()
295 {
296   myCleared = false;
297
298   bool ok = true;
299   bool done = false;
300   double newVal = 0;
301   if ( !specialValueText().isEmpty() )
302   {
303           QString s = QString( text() ).stripWhiteSpace();
304           QString t = QString( specialValueText() ).stripWhiteSpace();
305           if ( s == t )
306     {
307       newVal = minValue();
308             done = true;
309     }
310   }
311   if ( !done )
312           newVal = mapTextToDoubleValue( &ok );
313   if ( ok )
314           setValue( newVal );
315   updateDisplay();
316 }
317
318 void QtxDblSpinBox::valueChange()
319 {
320   updateDisplay();
321   emit valueChanged( value() );
322   emit valueChanged( currentValueText() );
323 }
324
325 void QtxDblSpinBox::rangeChange()
326 {
327   double min = QMIN( myMin, myMax );
328   double max = QMAX( myMin, myMax );
329   myMin = min;
330   myMax = max;
331   if ( validator()->inherits( "QDoubleValidator" ) )
332     ((QDoubleValidator*)validator())->setRange( myMin, myMax );
333
334         if ( myMin == myMax )
335                 QSpinBox::setRange( 0, 0 );
336         else
337                 QSpinBox::setRange( 0, 2 );
338
339   setValue( myValue );
340   updateDisplay();
341 }
342
343 QString QtxDblSpinBox::currentValueText()
344 {
345   QString s;
346   if ( (myValue == minValue()) && !specialValueText().isEmpty() )
347           s = specialValueText();
348   else
349         {
350           s = prefix();
351                 s.append( mapValueToText( myValue ) );
352                 s.append( suffix() );
353         }
354   return s;
355 }
356
357 QString QtxDblSpinBox::mapValueToText( double v )
358 {
359         QString s;
360   s.setNum( v, myPrecision < 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) );
361   return s;
362 }
363
364 QString QtxDblSpinBox::mapValueToText( int )
365 {
366   QString s;
367   s.setNum( myValue, myPrecision < 0 ? 'f' : 'g', myPrecision == 0 ? 6 : QABS( myPrecision ) );
368   return s;
369 }
370
371 double QtxDblSpinBox::mapTextToDoubleValue( bool* ok )
372 {
373   QString s = text();
374   double newVal = s.toDouble( ok );
375   if ( !(*ok) && !( !prefix() && !suffix() ) )
376   {
377           s = cleanText();
378           newVal = s.toDouble( ok );
379   }
380   return newVal;
381 }
382
383 double QtxDblSpinBox::bound( double val )
384 {
385   double newVal = val;
386   if ( newVal > myMax )
387     newVal = myMax;
388   if ( newVal < myMin )
389     newVal = myMin;
390   return newVal;
391 }
392
393 void QtxDblSpinBox::leaveEvent( QEvent* e )
394 {
395         if ( !myCleared )
396                 QSpinBox::leaveEvent( e );
397 }
398
399 void QtxDblSpinBox::wheelEvent( QWheelEvent* e )
400 {
401   if ( !isEnabled() )
402     return;
403
404   QSpinBox::wheelEvent( e );
405   updateDisplay();
406 }
407
408 void QtxDblSpinBox::onTextChanged( const QString& str )
409 {
410   bool isBlock = myBlocked;
411   myBlocked = true;
412   interpretText();
413   myBlocked = isBlock;
414 }